8

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()また、逆シリアル化されたコードオブジェクト(を介して読み取る)で使用する場合、表示されるのはand formarshal.load()だけであることに気付きましたが、このように使用するとLOAD_NAMECALL_FUNCTIONmain()import

import dis, sys

import simple
dis.dis(sys.modules["simple"])

それは私に期待通りに全体の分解を与えます。

Pythonがコンパイルに使用するコードのいくつかを見たことがありimportます。定義に何らかのルックアップテーブルを使用していると思いますがcompile()、この動作の原因となる違いが何であるかはわかりません。

4

2 に答える 2

0

このスクリプトは、simple.py コードを 3 回正常に実行します。これは何かを明確にしますか?それとも私はあなたの質問を誤解していますか?

# from original example
with open('simple.py', 'r') as f:
    code = f.read()
exec(code)
# compile and run again
a = compile(code, "simple_compiled_this_file_not_created", "exec")
exec(a)
# marshal and unmarshal
import marshal
f = open("./marshalfoo.bin", "wb")
marshal.dump(a,f) 
f.close()
b = marshal.load(open("./marshalfoo.bin", "rb"))
exec(b)
于 2012-08-29T19:54:03.930 に答える