2013/3/26 anatoly techtonik <[email protected]>
> 3. Now the problem. When I run execfile() without parameters, I expect the
> code inside to be 'virtualized' - isolated from parent process, like in LXC
> or VirtualBox, but on Python level. I also expect that if I want to
> communicate with this code inside execfile(), I craft my own
> 'first_namespace' and pass it down. When execfile() returns, I inspect the
> state of this modified namespace, and maybe import some results back into
> my 'current_namespace'. The example with indef.py above shows the
> execfile() doesn't work this way. So the question is - why execfile()
> doesn't it work the way I described?
>
You should always pass locals and globals to execfile(). I warned you :-)
No, the code is not isolated from the parent. When you call execfile only
with a filename, globals is set tho the caller's globals, and locals are
set to the caller's locals!
> 4. At this point I hope to reach the state there it is clear how
> execfile() works in reality, and the next question in this state - what was
> the reason to make it so complicated? Optimization?
>
OK, here is an explanation of what you probably call the "Python Execution
Context":
- All Python code runs with two namespaces: locals and globals.
- When running a script, or when a module is imported, there is only one
namespace: locals() is globals().
- When a function object is created "def...", the globals namespace is
captured, and stored in the function object.
When the function is executed, a new locals namespace is created, and
filled with the function arguments.
The function bytecode is executed with these locals; globals is the one
captured above.
- [Missing: the class statement]
When running bytecode:
- All assignments go into the locals namespace (this includes "x+=1", but
also "import sys")
- Name lookups first search locals, then globals.
- Except inside a function scope ("def", or a lambda), where the compiler
determines whether the name is a local variable
(it has an assignment in the same scope), in this case only the locals
are searched; otherwise only globals are searched.
[For this discussion, it's only an implementation detail and makes no
difference here]
- [Also missing: nested scopes and cells]
I think this explains all the weirdness you see:
- "import subprocess" is an assignment, and will populate the local
namespace.
- when ret() sees the "subprocess" name, it will lookup the globals
namespace.
In a normal script/module, this makes no difference, because locals() is
globals().
But with execfile(), globals and locals are passed from the parent frame:
- when execfile() is called at module level, they are identical: locals()
is globals() in the caller.
- when execfile() is called inside a function, they are different! And boom.
In other words, follow the advice above:
namespace = {}
execfile('indef.py', namespace)
This will pass the same namespace for both globals and locals,
and indef.py will be executed a bit like "import" or a standalone script.
--
Amaury Forgeot d'Arc
_______________________________________________
pypy-dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-dev