在玩弄marshal模块compile()
和. 我遇到了一些令人困惑的行为。考虑 exec
simple.py
def foo():
print "Inside foo()..."
def main():
print "This is a simple script that should count to 3."
for i in range(1, 4):
print "This is iteration number", i
foo()
if __name__ == "__main__":
main()
exec
当我像这样运行这个脚本时
with open('simple.py', 'r') as f:
code = f.read()
exec code
它给出了预期的输出。
This is a simple script that should count to 3.
This is iteration number 1
This is iteration number 2
This is iteration number 3
Inside foo()...
但是,如果我像这样介绍compile()
,marshal.dump()
和marshal.load()
import marshal
def runme(file):
with open(file, "r") as f:
code = marshal.load(f)
exec code
with open("simple.py", "r") as f:
contents = f.read()
code = compile(contents, "simple.py", "exec")
with open("marshalled", "w") as f:
marshal.dump(code, f)
runme("marshalled")
它打印预期输出的开头,然后出错
This is a simple script that should count to 3.
This is iteration number 1
This is iteration number 2
This is iteration number 3
Traceback (most recent call last):
File "./exec_within_function.py", line 17, in <module>
runme("marshalled")
File "./exec_within_function.py", line 8, in runme
exec code
File "simple.py", line 15, in <module>
main()
File "simple.py", line 12, in main
foo()
NameError: global name 'foo' is not defined
为什么它说foo
没有定义?
为了理解,我尝试dir()
像这样使用
import simple # imports simple.py
dir(simple)
正如预期的那样,它表明foo
已定义。
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'foo', 'main']
我还注意到,当我dis.dis()
在反序列化代码对象(通过读取marshal.load()
)上使用时,我看到的唯一东西是LOAD_NAME
and CALL_FUNCTION
for main()
,但是当我这样做import
时
import dis, sys
import simple
dis.dis(sys.modules["simple"])
它按预期给了我整个反汇编。
我什至查看了 python 用于编译的一些代码,虽然我认为import
使用某种查找表进行定义,但我不确定compile()
导致这种行为的区别是什么。