473,698 Members | 2,275 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

exec(), execfile() and local-variable binding?

I'm puzzled by Python's behavior when binding local variables which
are introduced within exec() or execfile() statements. First, consider
this simple Python program:

# main.py
def f() :
x = 1
print "x:", x

This just prints "x: 1" when run. Now, what happens if we move the
assignment into a separate file "assign.py" , and attempt to read it in
with execfile()?

# assign.py
x = 1
print "x in assign.py:", x

# main_execfile.p y
def f () :
execfile("assig n.py")
print "x in main_execfile.p y:", x

So, you might assume that if execfile() worked like a C-style
#include, this would work fine. But it doesn't. Instead, when
"main_execfile. py" is compiled, the "x = 1" assignment in "assign.py"
is never seen, so the 'x' in the print statement is assumed to be a
global variable. Then at run-time, we get an error about 'x' being an
undefined global variable:

x in assign.py: 1
x in main_execfile.p y:
Traceback (most recent call last):
File "main_execfile. py", line 4, in ?
File "main_execfile. py", line 3, in f
print "x in main_execfile.p y:", x
NameError: global name 'x' is not defined

Well, that's understandable. But what I find strange is that exec()
*doesn't* work in this way. Consider this version:

# main_exec.py
def f() :
exec("x = 1")
print "x:", x

I would have thought that, just like the execfile() version, the "x =
1" string would not be interpreted at parse-time, so that the 'x' in
the "print" statement would again be taken to be a global variable.
But no, this version runs fine, producing the output "x: 1".

And this fancier version also runs:

# main_exec2.py
def f(v) :
exec(v + " = 1")
print "x:", x
print "Type 'x':"

Here, if the user enters 'x', the assignment string "x = 1" is made
up, and the program runs as before.

So, why do these exec() versions work, when the execfile() one didn't?
Specifically, why aren't the 'x' variables in the "print" statements
taken as global variables? AFAIK, this should be a compile-time
decision, but the "x = 1" assignment strings can't have been
interpreted at that time.

Thanks for any help,

-- Jonathan
Jul 18 '05 #1
2 17386
jo*****@excite. com (Jonathan) wrote in message news:<c0******* *************** ****@posting.go ogle.com>...
I'm puzzled by Python's behavior when binding local variables which
are introduced within exec() or execfile() statements. [...]

I now think I understand the gist of the problem. A Google group
search turned up some very similar past discussions. Essentially,
execfile() is a function, and so can't (reliably) change the
local-variable dictionary (locals()) which is passed into it. So any
local-variable settings which happen in the file which execfile()
executes are lost when it returns.

In contrast, exec() is a *statement*, not a function. Therefore, the
locals() dictionary passed into it is mutable. So variable assignments
in the string of an exec() *will* affect the local-variable dictionary
of the function which calls it. Python's usual static compile-time
variable binding can't cope with these potential dynamically-defined
variables. So therefore, if any exec() statement is seen in a function
body at compile-time, static binding is switched off, and a slower
form of run-time binding is used. This dynamically searches the
enclosing variable scopes (dictionaries) for variable definitions.

The run-time binding triggered by exec() explains a weird effect which
I stumbled on after I posted my original message. That is, the
execfile() version of the code *will* work if an exec() appears
anywhere before or after it in the f() function definition. This is
because run-time binding is now used for the whole function - even for
the execfile(). That's why I said above that execfile() can't
*reliably* change the calling function's local-variable dictionary -
it can if this run-time-binding mode is in effect.

Such sneaky insertion of a dummy exec() is not great form, though. The
recommended way to allow execfile() code to affect current variables
is to pass in an explicit context dictionary as an argument to
execfile(). Then you are free to use that dictionary as you see fit
(notably, using it for other exec()'s or execfile()'s). Another way to
implement more of a #include-type effect is to replace this:
execfile("blah. py")
with this:
exec open("blah.py") .read()

However, once again, this solution will trigger the use of the slower
run-time binding for the whole enclosing function.

I trust the experts out there will comment if I misrepresented any of
these issues.

-- Jonathan
Jul 18 '05 #2
Quoth Jonathan:
Well, that's understandable. But what I find strange is that exec()
*doesn't* work in this way. Consider this version:

# main_exec.py
def f() :
exec("x = 1")
print "x:", x

Note that exec is a keyword, not a function; you might as well
exec 'x = 1'
I'm not just picking a nit here -- it is important for your
question that exec is a keyword, since this means it is possible
to determine at compile-time whether exec is used in the body of a
function. This is quite unlike calls to built-in functions such
as execfile(), which cannot in general be identified as such at

As you noted, in the presence of exec statements, the compiler
abandons the optimization by which LOAD_NAMEs are replaced with
LOAD_GLOBALs. This optimization normally speeds up variable
access by skipping a futile name lookup in the locals; abandoning
this optimization when there are exec statements makes your
example above work in the obvious and desired way.

Steven Taschuk st******@telusp lanet.net
"I tried to be pleasant and accommodating, but my head
began to hurt from his banality." -- _Seven_ (1996)

Jul 18 '05 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

by: | last post by:
Hi everybody, I'm sure there's a way to do this, but I can't find it. How can I execute another .py file from my first .py file without using an exec* command? They're both in the same directory, and it would be nice to have some run("another.py") type statement as opposed to a big exec with absolute pathnames and garbage like that. It works the way I have it, but it just seems like a bad way in general to do it. I'm runnning Python...
by: Chris S. | last post by:
I'd like to dynamically execute multiple lines of indented code from within a script, but I can't seem to find a suitable function. Exec only works with unindented code, and execfile only works with files. I suppose I could write my string to a temporary file and then use execfile, but that seems like a hack. Is there an easier way? Any help is appreciated.
by: tedsuzman | last post by:
----- def f(): ret = 2 exec "ret += 10" return ret print f() ----- The above prints '12', as expected. However,
by: Andr? Roberge | last post by:
I have the following two files: #--testexec.py-- def exec_code(co): try: exec co except: print "error" #-- test.py--
by: Bo Jacobsen | last post by:
I have a number of files compiled to bytecode using py_compile.compile(). The .pyc files can be invoked by python directly ($python file.pyc), but "loading" them by execfile just throws an exception ? Any suggestions Bo.
by: R. Bernstein | last post by:
In doing the extension to the python debugger which I have here: http://sourceforge.net/project/showfiles.php?group_id=61395&package_id=175827 I came across one little thing that it would be nice to get done better. I notice on stack traces and tracebacks, an exec or execfile command appears as a stack entry -- probably as it should since it creates a new environment. However the frame information for exec or execfile looks like this:...
by: xml0x1a | last post by:
How do I use exec? Python 2.4.3 ---- from math import * G = 1 def d(): L = 1 exec "def f(x): return L + log(G) " in globals(), locals() f(1)
by: Edward K Ream | last post by:
It looks like both exec and execfile are converting "\n" to an actual newline in docstrings! Start idle: Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) on win32
by: Fernando Perez | last post by:
Hi all, I'm finding the following behavior truly puzzling, but before I post a bug report on the site, I'd rather be corrected if I'm just missing somethin obvious. Consider the following trivial script: # Simple script that imports something from the stdlib from math import sin, pi
by: George Sakkis | last post by:
I maintain a few configuration files in Python syntax (mainly nested dicts of ints and strings) and use execfile() to read them back to Python. This has been working great; it combines the convenience of pickle with the readability of Python. So far each configuration is contained in a single standalone file; different configurations are completely separate files. Now I'd like to factor out the commonalities of the different...
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.