M
Mitchell L Model
[Python 3.1]
I thought I thoroughly understood eval, exec, globals, and locals, but I
encountered something bewildering today. I have some short files I
want to
exec. (Users of my application write them, and the application gives
them a
command that opens a file dialog box and execs the chosen file. Users
are
expected to be able to write simple Python scripts, including function
definitions. Neither security nor errors are relevant for the purposes
of this
discussion, though I do deal with them in my actual code.)
Here is a short piece of code to exec a file and report its result.
(The file
being exec'd must assign 'result'.)
def dofile(filename):
ldict = {'result': None}
with open(filename) as file:
exec(file.read(), globals(), ldict)
print('Result for {}: {}'.format(filename, ldict['result']))
First I call dofile() on a file containing the following:
################################
def fn(arg):
return sum(range(arg))
result = fn(5)
################################
The results are as expected.
Next I call dofile() on a slightly more complex file, in which one
function
calls another function defined earlier in the same file.
################################
def fn1(val):
return sum(range(val))
def fn2(arg):
return fn1(arg)
result = fn2(5)
################################
This produces a surprise:
NameError: global name 'fn1' is not defined
[1] How is it that fn2 can be called from the top-level of the script
but fn1
cannot be called from fn2?
[2] Is this correct behavior or is there something wrong with Python
here?
[3] How should I write a file to be exec'd that defines several
functions that
call each other, as in the trivial fn1-fn2 example above?
I thought I thoroughly understood eval, exec, globals, and locals, but I
encountered something bewildering today. I have some short files I
want to
exec. (Users of my application write them, and the application gives
them a
command that opens a file dialog box and execs the chosen file. Users
are
expected to be able to write simple Python scripts, including function
definitions. Neither security nor errors are relevant for the purposes
of this
discussion, though I do deal with them in my actual code.)
Here is a short piece of code to exec a file and report its result.
(The file
being exec'd must assign 'result'.)
def dofile(filename):
ldict = {'result': None}
with open(filename) as file:
exec(file.read(), globals(), ldict)
print('Result for {}: {}'.format(filename, ldict['result']))
First I call dofile() on a file containing the following:
################################
def fn(arg):
return sum(range(arg))
result = fn(5)
################################
The results are as expected.
Next I call dofile() on a slightly more complex file, in which one
function
calls another function defined earlier in the same file.
################################
def fn1(val):
return sum(range(val))
def fn2(arg):
return fn1(arg)
result = fn2(5)
################################
This produces a surprise:
NameError: global name 'fn1' is not defined
[1] How is it that fn2 can be called from the top-level of the script
but fn1
cannot be called from fn2?
[2] Is this correct behavior or is there something wrong with Python
here?
[3] How should I write a file to be exec'd that defines several
functions that
call each other, as in the trivial fn1-fn2 example above?