Re: execfile (exec?) create non consistent locals() state

Discussion in 'Python' started by Chris Rebert, Apr 21, 2009.

  1. Chris Rebert

    Chris Rebert Guest

    On Tue, Apr 21, 2009 at 11:25 AM, Doron Tal <> wrote:
    > On Tue, Apr 21, 2009 at 9:13 PM, Chris Rebert <> wrote:
    >>
    >> On Tue, Apr 21, 2009 at 9:08 AM, Doron Tal <>
    >> wrote:
    >> > Hi,
    >> >
    >> > Recently I tried to execute a python file using execfile (exec performed
    >> > just the same for that reason).
    >> > I encountered the behavior below:
    >> >
    >> > """
    >> > $ cat execme.py
    >> > a = 2
    >> > $ python
    >> > Python 2.4.3 (#1, May 24 2008, 13:57:05)
    >> > [GCC 4.1.2 20070626 (Red Hat 4.1.2-14)] on linux2
    >> > Type "help", "copyright", "credits" or "license" for more information.
    >> >>>> def execfile_func():
    >> > ...     execfile('execme.py')
    >> > ...     print 'locals() = %s' % str(locals())
    >> > ...     print a
    >> > ...
    >> >>>> execfile_func()
    >> > locals() = {'a': 2}
    >> > Traceback (most recent call last):
    >> >   File "<stdin>", line 1, in ?
    >> >   File "<stdin>", line 4, in execfile_func
    >> > NameError: global name 'a' is not defined
    >> >>>>
    >> > """
    >> >
    >> > After execfile, the a variable can be found in locals(), however any
    >> > direct
    >> > reference (e.g., print a) fails.
    >> > Is it expected?

    >>
    >> Yes. See http://docs.python.org/library/functions.html#locals (emphasis
    >> mine):
    >>
    >> locals()
    >>    [...]
    >>    Warning: The contents of this dictionary should not be modified;
    >> ***changes may not affect the values of local variables used by the
    >> interpreter***.
    >>    [...]
    >>
    >> Cheers,
    >> Chris
    >> --
    >> I have a blog:
    >> http://blog.rebertia.com

    >
    > (Chris - sorry for the multiple replies, I forgot to reply all)
    >
    > I actually did not attempt to modify this dictionary (the one which locals()
    > returns) explicitly.


    Well, it can be reasonably inferred that execfile() does.

    > The simplest assignment command, such as 'a = 2' modifies this dictionary
    > implicitly, and it's working perfectly well.


    While the exec'd file may run fine using the locals() dict (or any
    dict for that matter), that doesn't say anything about whether the
    changes to locals() will actually be reflected in the local namespace
    it came from, which indeed, as documented, it's not. execfile() may
    use the locals() dict for all its variable lookups, but the plain
    toplevel interpreter is allowed not to.

    > I expected exec to work the same, but apparently I was wrong. Is there is a
    > way to exec a file "more" correctly? thus avoid the need to resort to
    > awkward solutions such as using the locals() dictionary?


    I don't know personally. Perhaps a kind soul will chime in.

    Cheers,
    Chris

    --
    I have a blog:
    http://blog.rebertia.com
    Chris Rebert, Apr 21, 2009
    #1
    1. Advertising

  2. Chris Rebert

    Peter Otten Guest

    [original post is not on my news server]

    [Doron Tal]

    >>> > Recently I tried to execute a python file using execfile (exec
    >>> > performed just the same for that reason).


    Not not over here here:

    Python 2.4.4 (#2, Aug 1 2008, 00:04:43)
    [GCC 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> def f():

    .... execfile("execme.py")
    .... print "locals:", locals()
    .... print a
    ....
    >>> f()

    locals: {'a': 2}
    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    File "<stdin>", line 4, in f
    NameError: global name 'a' is not defined
    >>> def g():

    .... exec open("execme.py").read()
    .... print "locals:", locals()
    .... print a
    ....
    >>> g()

    locals: {'a': 2}
    2

    The reason is that while execfile() is just an ordinary function the exec
    statement affects the function's bytecode (LOAD_NAME instead of LOAD_GLOBAL
    or LOAD_FAST). This leads to the following Voodoo:

    >>> def h():

    .... exec ""
    .... execfile("execme.py")
    .... print "locals:", locals()
    .... print a
    ....
    >>> h()

    locals: {'a': 2}
    2

    While this is certainly not the most regular behaviour it allows to avoid
    going through a dictionary for every assignment in functions that don't
    have an exec statement, thus giving you faster code in the vast majority of
    cases at the cost of a few quirks like the one you encountered.

    Peter
    Peter Otten, Apr 22, 2009
    #2
    1. Advertising

  3. Chris Rebert

    Peter Otten Guest

    [original post is not on my news server]

    [Doron Tal]

    >>> > Recently I tried to execute a python file using execfile (exec
    >>> > performed just the same for that reason).


    Not over here:

    Python 2.4.4 (#2, Aug 1 2008, 00:04:43)
    [GCC 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> def f():

    .... execfile("execme.py")
    .... print "locals:", locals()
    .... print a
    ....
    >>> f()

    locals: {'a': 2}
    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    File "<stdin>", line 4, in f
    NameError: global name 'a' is not defined
    >>> def g():

    .... exec open("execme.py").read()
    .... print "locals:", locals()
    .... print a
    ....
    >>> g()

    locals: {'a': 2}
    2

    The reason is that while execfile() is just an ordinary function the exec
    statement affects the function's bytecode (LOAD_NAME instead of LOAD_GLOBAL
    or LOAD_FAST). This leads to the following Voodoo:

    >>> def h():

    .... exec ""
    .... execfile("execme.py")
    .... print "locals:", locals()
    .... print a
    ....
    >>> h()

    locals: {'a': 2}
    2

    While this is certainly not the most regular behaviour it allows to avoid
    going through a dictionary for every assignment in functions that don't
    have an exec statement, thus giving you faster code in the vast majority of
    cases at the cost of a few quirks like the one you encountered.

    Peter
    Peter Otten, Apr 22, 2009
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jonathan
    Replies:
    2
    Views:
    518
    Steven Taschuk
    Aug 10, 2003
  2. tedsuzman
    Replies:
    2
    Views:
    7,062
    Michel Claveau, résurectionné d'outre-bombe inform
    Jul 21, 2004
  3. Ted
    Replies:
    1
    Views:
    451
    Duncan Booth
    Jul 22, 2004
  4. R. Bernstein
    Replies:
    8
    Views:
    388
    R. Bernstein
    Jan 16, 2006
  5. Replies:
    2
    Views:
    1,307
Loading...

Share This Page