How to eval a file

Alex Martelli aleax at aleax.it
Sun Feb 23 12:13:48 EST 2003


Björn Lindberg wrote:
   ...
>     def m(self):
>         execfile("../collection/collection.layout")
>         self.collection = collection
   ...
>     self.collection = collection
> NameError: global name 'collection' is not defined
>>>> 
> 
> The file has a line with "collection = 'bla, bla....'" in it.
> 
>>  execfile(...)
>>      execfile(filename[, globals[, locals]])
>> 
>>      Read and execute a Python script from a file.
>>      The globals and locals are dictionaries, defaulting to the current
>>      globals and locals.  If only globals is given, locals defaults to
>>      it.
> 
> So, if the globals and locals arguments defaults to the current scope,
> why don't I have a global variable 'collection' when the execfile returns?

See the more detailed Python docs online, e.g.:
http://www.python.org/doc/current/lib/built-in-funcs.html

"""
Warning: The default locals act as described for function locals() below: 
modifications to the default locals dictionary should not be attempted. 
Pass an explicit locals dictionary if you need to see effects of the code 
on locals after function execfile() returns. execfile() cannot be used 
reliably to modify a function's locals.
"""

If you think it would be helpful to you to understand the reasons
for this in greater detail, just ask, and I'll be glad to explain
them further.  But, basically, the bottom line is: not only you
*shouldn't* call execfile in order to (potentially) destroy your
function's local namespace, but attempting to do so need not work
reliably anyway.

I feel a bit like a firearms expert trying to help somebody who
complains that, when they point their new Beretta at their foot
and pull the trigger, it _doesn't_ blow their foot off, or at
least not all of the time.  It appears that the requestor may
not fully understand the implications of what would happen when
they DO finally manage to complete the task they're so keen on
attempting.  Still, the way to remove the safety and ensure the
destruction of your extremities is to use, instead of execfile:

    exec file("../collection/collection.layout").read()

When the Python compiler sees the 'exec' statement, it knows
what it's trying to do (because it's a statement, not a function
like eval or execfile) and therefore removes the optimizations
it normally performs (so your function containing this statement
will be dog-slow as well as probably buggy and undebuggable) to
guarantee that the foot's fate is sealed.


> However, if I include a dictionary as a second argument to execfile(),
> I can extract 'collection' from it, and it works like expected.

As well as being a bit faster and somewhat less likely to lead
to hard-to-debug bugs.  So I'm not quite sure why you're so keen
on doing otherwise.  Particularly because, when the dictionary
you include is self.__dict__, you'll get the variables that are
set in the file you execfile directly as instance variables of
self, which from your posts seems to be exactly what you're after,
so the approach would be more convenient and concise as well as
avoiding the other disadvantages I mentioned.


Alex





More information about the Python-list mailing list