Unexpected (by me) exec behavior

Adrien Di Mascio Adrien.DiMascio at logilab.fr
Wed Jul 9 08:29:55 CEST 2003

> ----------------------------
> # filename = t.py
> s1 = """
> s2 = \"\"\"
> import socket
> def xyz():
> 	print socket.gethostbyname('somehost')
> if __name__ == '__main__':
> 	xyz()
> \"\"\"
> def abc():
> 	exec s2
> if __name__ == '__main__':
> 	abc()
> """
> exec s1
> -----------------------------
I'll try to explain things as best as I can :
  - (1) When defining a variable in a new scope, it is added to the locals() dict.
  - (2) Calling exec without specifying any dict will cause to call it
        with globals() as global dict and locals() as local dict
  - (3) When you'll execute your script (t.py), globals() and locals()
        dict will be the same (they'll have the same id)

Consequences : 
  When you execute s1, globals() and locals() dict will be used, and
  they are the same. When entering the abc() func, a new local dict
  will be created (an "empty" one), so when you call exec s2, the two
  dict that will be taken will be globals(), and locals(), but they
  are not representing the same dict anymore since you're in the 'abc'
  scope and the locals() dict is thus "empty".
  When Python tries to execute s2, it will add socket into your local
  dict (not into the global one), then he will enter in the xyz()
  function, where it will create
  a new local dict because it will have just entered a new scope.
  Then in xyz(), neither globals(), nor locals() have a reference to
  'socket', that's why you have your NameError.

  To prevent this, you can always call "exec s2 in globals()" in the
  abc function. Then, both globals and locals will have the same id,
  so when Python will add "socket" to the locals dict, it will also
  add it to the globals() one, and "socket" will be found in the
  global dict.

Anyway, you're doing tricky things ...

Hope this helps.


Adrien Di Mascio
LOGILAB, Paris (France).
http://www.logilab.com   http://www.logilab.fr   http://www.logilab.org

More information about the Python-list mailing list