2012-09-20 16 views
21

私はそれをexecし、文字列内のインポート文を置くことができ、それが(ランダムな数字を出力します)作品:Pythonでは、関数内のexecのインポートはなぜ機能しませんか?

code = """ 
import random 
def f(): 
    print random.randint(0,9) 
""" 

def f(): 
    pass 

exec code 
f() 

を今、私は自分自身の機能でexec codef()を置けば、それを呼び出し、それはdoesnの仕事はありません。

def test(): 
    exec code 
    f() 

test() 

NameError: global name 'random' is not definedと書かれています。 何が起こっているか考えてみましょうか? おかげ

+0

好奇心で、なぜこれをしたいですか? –

+1

これは悪いデザインの兆候です。避けてください。 –

+0

+ Vincent Savard、私はPythonスクリプトを書くことができるJavaベースの製品を扱っています。また、あらかじめ定義された特定のイベントが発生したときにスクリプトを実行するように設定できます。しかし、関数をライブラリとして使いたい場合は、標準のimport文を使って別のスクリプトを読み込むことはできません。代わりに、私はデータベースから他のスクリプトのコードを読み込み、exec()する必要があります。そして、問題は、他のスクリプトが私がしなかったJavaライブラリをインポートするということです。その場合、ライブラリ関数を呼び出すと+ Alex Varga – Preacher

答えて

12

これはどう:

def test(): 
    exec (code, globals()) 
    f() 
3

はあなたがここでの問題は、あなたの関数のスコープではなく、グローバルスコープにrandomモジュールをインポートしていることであるグローバルrandomモジュール

code = """ 
import random 
def f(): 
    global random 
    print random.randint(0,9) 
""" 

を望んでいることを指定します。

14

ここで何が起こっているが、ランダムなモジュールがテスト内のローカル変数としてインポートされていることです。

def test(): 
    import random 
    def f(): 
     print random.randint(0,9) 
    f() 
:この

def test(): 
    exec code 
    print globals() 
    print locals() 
    f() 

frandomを見ることができない理由は、あなたがこれをしなかった--if ftestの内側にネストされた関数ではないということです

{'code': '\nimport random\ndef f():\n print random.randint(0,9)\n', '__builtins__': <module '__builtin__' (built-in)>, '__package__': None, 'test': <function test at 0x02958BF0>, '__name__': '__main__', '__doc__': None} 
{'random': <module 'random' from 'C:\Python27\lib\random.pyc'>, 'f': <function f at 0x0295A070>} 

を印刷します試してみてください

それは動作します。ただし、ネストされた関数では、外部関数をコンパイルするときに、外部関数に内部関数の定義が含まれている必要があります。これは、2つの(外部および内部)関数間で共有される変数を保持するセル変数を設定する必要があるためです。グローバル名前空間にランダム取得するには

、あなただけinキーワードの後に​​execして何か

exec code in globals(),globals() 

このような引数は、コードが実行されるグローバルとローカル名前空間です(したがってんだろう、 exec'dコードで定義されている名前が格納されます)。

関連する問題