How to eval a file

Alex Martelli aleax at aleax.it
Sun Feb 23 15:51:29 EST 2003


Björn Lindberg wrote:
   ...
> Oh, but I have already changed my implementation to actually parsing
> my configuration file instead. I continue to ask questions beacuse I
> suspect I do not yet fully understand how namespaces work in Python,
> and I want to understand it.

I think this is an excellent motivation.  A local namespace is
indeed special, because of a key optimization the Python
compiler normally does: as it compiles a function's body it
notices all names that are assigned in the body (assignment
statements, argument names, def, class, import) and deems them
local (unless they're listed in a global statement).  Lookup
of locals does NOT use general-purpose lookup strategies (which
can be costly) but rather uses an index directly into a list
of those locals' values.

Therefore, even though you can LOOK at the local namespace
as a dictionary (built-in function locals) you cannot ALTER
that namespace reliably -- in particular, adding names that
the compiler had not classified as locals of the function.

If the compiler notices an exec statement in your function's
body, then the compiler turns the optimization partly off.  A
similar effect is obtained by other statements that, in a way
known to the compiler, must be able to define arbitrary names
at runtime, such as "from aaaargh import *".  Such statements
are very bad practice, but unfortunately they're required to
work, and thus, the compiler detects them and turns off the
optimization (thus making the function slower as well as very
likely buggy and hard to debug;-).

The optimization is only _partly_ off because the compiler
still generates LOAD_FAST and STORE_FAST bytecode instructions
for those names it KNOWS are local; however, it must generate
the more general LOAD_NAME rather than the more specialized
LOAD_GLOBAL for references to names it *doesn't know* are
local (as opposed to *know aren't local* when the optimization
is fully on;-).  Whether this partial disabling makes any
important performance difference depends too much on how many
references the rest of the function's body -- however, to be
quite honest (but don't tell anybody...) it's unlikely to be
anything major.  I keep mentioning the performance loss, without
mentioning that it's probably a minor factor, just because I
do hope to scare off some performance-crazed programmers from
the bad practices of "from blah import *" and exec...;-).


Alex





More information about the Python-list mailing list