Fernando Perez wrote: > 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: > > from math import sin, pi > wav = lambda k,x: sin(2*pi*k*x) > print wav(1,0.25)
> The above runs just fine from a prompt, or even interactively via > execfile(). Now, consider calling it by using this instead: > > #!/usr/bin/env python > def runscript(fname): > """Run a file by calling execfile().""" > execfile(fname) > runscript('execfilebugscript.py') > If I run the above, calling the first script 'execfilebugscript.py' and > the second 'execfilebug.py', I get this: > NameError: global name 'sin' is not defined > I'm really, really puzzled by this. From reading the execfile() docs, I > had the hunch to change the call to: > > execfile(fname,{}) > > and now the problem disappears, so I can keep on working. If you execfile() a script names not known in the context of a function are looked up in the global namespace, but assignments set names in the local namespace. Consider execfile(filename) for a file x = 42 def f(): print x f() x and f are put into the local namespace, but x is not local to the function f and therefore looked up in f's globals. Now if you call execfile() in the global namespace of the client script the global and local namespace are identical >>> globals() is locals() True so x although put into the local namespace will still be found when looked up in the global namespace. That is the same situation as in your workaround execfile(filename, {}). This however is not the case if you call execfile() inside a function. Here global and local namespace differ. In your example, when you put another execfile() into the global namespace of the client script the sin() imported there is the only one that your wav() function sees. You can verify that by putting def sin(phi): return "I'm not math.sin()" instead of if 1: .... into execfilebug.py. Can the current behaviour of execfile() be changed into a more intuitive one? Not with only two namespaces. You'd probably need something similar to closures, and I don't think the necessary work would be worth the effort. Peter -- http://mail.python.org/mailman/listinfo/python-list