By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
426,012 Members | 988 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 426,012 IT Pros & Developers. It's quick & easy.

exec and global puzzle

P: n/a
I have the following two files:

#--testexec.py--
def exec_code(co):
try:
exec co
except:
print "error"

#-- test.py--
import thread
import testexec
import time

code = "def a():\n print 'a'\n\n" +\
"def c():\n a()\n\nc()"

code2 = "def a():\n print 'a'\n\n" +\
"def c():\n global a\n a()\n\nc()"

print " exec code - no global"
exec code
print " exec from thread - no global"
thread.start_new(testexec.exec_code, (code,))
time.sleep(1)
print "\n exec code2 - with global"
exec code2
print " exec from thread - with global"
thread.start_new(testexec.exec_code, (code2,))
#-----------------------

Here's the output when I execute test.py:

exec code - no global
a
exec from thread - no global
error

exec code2 - with global
a
exec from thread - with global
a
#---------
Without the global statement, I get an error when trying to execute
the code.
I don't understand why I need to use the global statement within the
definition of c() in order for it to know what a() is. If I define
exec_code() within test.py and use it there, I do not get any error,
with or without the use of a global statement.

Andre
Jul 18 '05 #1
Share this Question
Share on Google+
1 Reply


P: n/a
Andr? Roberge wrote:
I have the following two files:

#--testexec.py--
def exec_code(co):
try:
exec co
except:
print "error"

#-- test.py--
import thread
import testexec
import time

code = "def a():\n print 'a'\n\n" +\
"def c():\n a()\n\nc()"

code2 = "def a():\n print 'a'\n\n" +\
"def c():\n global a\n a()\n\nc()"

print " exec code - no global"
exec code
print " exec from thread - no global"
thread.start_new(testexec.exec_code, (code,))
time.sleep(1)
print "\n exec code2 - with global"
exec code2
print " exec from thread - with global"
thread.start_new(testexec.exec_code, (code2,))
#-----------------------

Here's the output when I execute test.py:

exec code - no global
a
exec from thread - no global
error

exec code2 - with global
a
exec from thread - with global
a
#---------
Without the global statement, I get an error when trying to execute
the code.
I don't understand why I need to use the global statement within the
definition of c() in order for it to know what a() is. If I define
exec_code() within test.py and use it there, I do not get any error,
with or without the use of a global statement.

Andre


I have taken the liberty of restructuring your program slightly, by
using a "from" to explicitly import the function you need, and by using
extended string literals (""" ... """) to make the code easier to read.
I have also included print statements to show the contents of the local
and global namespaces after the definition of function a(). After these
transformations it looks like this:

import thread
from testexec import exec_code
import time

code = """\
def a():
print 'a'

def c():
a()

c()
"""

code2 = """\
def a():
print 'a'

def c():
global a
a()

c()
"""

print " exec code - no global"
exec code
print " exec from thread - no global"
thread.start_new(exec_code, (code,))
time.sleep(1)
print "\n exec code2 - with global"
exec code2
print " exec from thread - with global"
thread.start_new(exec_code, (code2,))
time.sleep(1)

(OK, I added a final sleep so I saw the output from the second thread).

The reason you are seeing this behavior lies in the behavior of the exec
statement. The full syntax for that statement is

exec_stmt ::= "exec" expression ["in" expression ["," expression]]

The second and third expressions are mappings that will be used as
namespaces. Since you don't provide either, the interpreter uses the
current scope (whose contents can be determined using the locals()
function) for both namespaces, so it doesn't matter whether the function
is added to the local or the global namespace.

When using threads, however (and, by the way, the usual advice is to use
the threading module, which has a more convenient API), the namespaces
are clearly different. The a() function is being added to the local
namespace for the exec.

So ultimately it's to do with namespaces, as many of the more perplexing
problems in Python are. I hope this helps establish exactly *why* you
see what you do.

regards
Steve
--
http://www.holdenweb.com
http://pydish.holdenweb.com
Holden Web LLC +1 800 494 3119
Jul 18 '05 #2

This discussion thread is closed

Replies have been disabled for this discussion.