2017-05-22 2 views
0

文字列にコードを格納しています(ユーザがアプリケーションのテキストボックスにこれを編集します)。このコードには、multiprocess.Poolを使って後で実行したい機能があります。しかし、文字列に定義されている関数がネストされている場合は機能しません。マルチプロセスではネストされた関数とうまく動作しない場合があります

標準multiprocessingではなく、multiprocessを使用していますが、文字列に定義されている関数を実行することはできません。

何が起こるかは、次のスニペットのコメントを参照してください。私のシナリオで使用できる回避策はありますか?

funcs = """ 
def func(x): 
    return func_inner(x) + 1 

def func_inner(x): 
    return x + 1 
""" 

import multiprocess 

if __name__ == "__main__": 
    symbols = dict() 
    exec(funcs, symbols) 
    func = symbols["func"] 
    print(func(1)) # this is evaluated correctly as 3 so nesting functions work fine! 
    data = [1, 2, 3] 
    pool = multiprocess.Pool() 
    print(pool.map(func, data)) # this fails with NameError: name 'func_inner' is not defined! 

私はこれをWindowsとLinuxでも試しました。私のmultiprocessバージョンは0.70.5とPython 3.5です。

答えて

0

は、あなたは自分の文字列ベースの機能のためにcompile()を逃しているようだ:私のために

funcs=compile(""" 
def func(x): 
    return func_inner(x) + 1 

def func_inner(x): 
    return x + 1 
""", '<string>', 'exec') 

if __name__ == "__main__": 
    import multiprocess 

    symbols = dict() 
    exec(funcs, symbols) 
    func = symbols["func"] 
    print(func(1)) 
    data = [1, 2, 3] 
    pool = multiprocess.Pool() 
    print(pool.map(func, data)) 

出力:[3、4、5]

UPDATE: 私のマルチバージョンがある - 0.70.4 はあなたのために働く必要があり、以下の汚い修正を試してみてください。

import multiprocess 

code_globals = {} 
code_locals = {} 
exec funcs in code_globals, code_locals 
print code_locals 
# {'func_inner': <function func_inner at 0x10aa607d0>, 'func': <function func at 0x10a97dde8>} 

code_globals['func_inner']=code_locals['func_inner'] 

print code_globals['func_inner'] 
#<function func_inner at 0x10a1427d0> 

func = code_locals['func'] 
print(func(1)) 
data = [1, 2, 3] 
pool = multiprocess.Pool() 
print(pool.map(func, data)) 
+0

、私はそれはまだ前と同じエラーで私のために失敗したかと思います。 –

+0

どの 'マルチプロセス 'バージョンがありますか?最近のバージョンでは特定のことが壊れていると思われます。 –

+0

'code_globals ['func_inner'] = code_locals ['func_inner']'を追加すると、コードスニペットが機能することが確認できます。しかし、実際には、私は事前にわかっていないので、実際にはこの関数は使用できません。入れ子になっているプールによって呼び出される関数は、 'code_globals.update(code_locals)'のようなものが必要ですすべてのローカルシンボルをグローバルシンボルに変換します。しかし、この線では、サンプルは再び壊れます。 –

関連する問題