在玩弄marshal模块compile()和. 我遇到了一些令人困惑的行为。考虑 execsimple.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_NAMEand CALL_FUNCTIONfor main(),但是当我这样做import时
import dis, sys
import simple
dis.dis(sys.modules["simple"])
它按预期给了我整个反汇编。
我什至查看了 python 用于编译的一些代码,虽然我认为import使用某种查找表进行定义,但我不确定compile()导致这种行为的区别是什么。