From: Samuele P. <ped...@bl...> - 2002-12-20 18:23:07
|
From: "Stefan Baramov" <Ste...@tr...> > Hi Oti, > > Thanks a lot for the response. And I have also tried the workaround and they > work. > > Unfortunately these two scripts are very simplified example of a much more > complicated system and the work around is not quite acceptable. I am more > interested to find out whether this is a bug or not. And if it is a bug is > it fixed. If it is I can eventually grab the latest and the greatest from > CVS and build my one version of Jython but before investing time and efforts > I would really like to know whether this is fixed or not. > First what you is see not a bug, although I have no problem to admit that what happens is for sure confusing. Let's consider this similar example: <a.py> def a(): print "a" </a.py> <b.py> from a import a def b(): a() b() </b.py> <c.py> def c(): execfile('b.py') c() </c.py> Now even with CPython we get: C:\exp\jy-execfile-confusion>\usr\Python22\python -V Python 2.2.1 C:\exp\jy-execfile-confusion>\usr\Python22\python c.py Traceback (most recent call last): File "c.py", line 5, in ? c() File "c.py", line 3, in c execfile('b.py') File "b.py", line 7, in ? b() File "b.py", line 5, in b a() NameError: global name 'a' is not defined Obviously OTOH b.py stand-alone works. When b.py is run stand-alone the code inside it is executed with local namespace = global namespace (= __main__ module's namespace). 1) the import statement binds a in the local namespace (= global namespace) to the function from module a . 2) the definition of b captures the current global namespace (= local namespace) as the global namespace to be used when b is executed, and b is bound in the local namespace (= global) to the defined function. 3) b is invoked, a is not locally bound inside b so it is searched in the global namespace associated with the function (the one captured in 2) and our function a from module a is found and all goes well. The essential point is that the local namespace modified by import (2) is the same as the global namespace searched in (3). This happens because local namespace = global executing b.py standalone. Now to c.py: from the description of execfile(file[, globals[, locals]]) in the Python Library Reference: http://www.python.org/doc/2.1.3/lib/built-in-funcs.html#l2h-169 "If the locals dictionary is omitted it defaults to the globals dictionary. If both dictionaries are omitted, the expression is executed in the environment where execfile() is called." the latter (it's our case in c) means that the code in b.py is executed with local namespace = local namespace of function c execution BUT global namespace = global namespace of c function = c module's namespace. The two namespaces are different, a is bound in one namespace, and then there is no a to retrieve from c module's namespace, so the error. Yes, this can be indeed confusing. In conclusion: Unless it is used at the top-level (where it can be thought to be roughly equivalent to an include), it is better not to use the only-file-arg version of execfile and instead: ns = {} # possibly bind some value in ns to be passed to the executed code execfile(file,ns) in this way the execution will happen under the more sane local namespace = global namespace. So returning to our example, such a c.py: def c(): execfile('b.py',{}) c() would work. regards. |