2017-06-04 6 views
0

動的にインポートされたモジュールから追加機能をsingledispatch関数に登録しようとしています。動的にインポートされたモジュールでsingledispatch関数を登録する

main.py

from importlib import import_module 
from functools import singledispatch 

@singledispatch 
def handle(a): 
    return 'default' 

def import_something(): 
    other_module = import_module('dynimp') 
    handle_result = handle(1) 
    assert handle_result == 'int', f'Error: {handle_result}' 

if __name__ == '__main__': 
    import_something() 

dynimp.py

from main import handle 

@handle.register(int) 
def handle_int(a): 
    return 'int' 

import_somethingでアサーションが失敗し、私は'default'、ない'int'を取得します。

もう少し調べました。関数オブジェクトは、dynimpにインポートされると何とかコピーされます。 other_module = import_module('dynimp')の後にブレークポイントを設定した場合、other_module.handle != handleother_module.registryhandle.registryのようにhandle_intと表示されます。その後、

def do_register(handle_fn): 
    handle_fn.register(int, handle_int) 

import_something機能でother_module.do_register(handle)を追加します。

機能するソリューションは、dynimp.pyregister機能を持っており、それをhandleを渡すことです。

私の質問は次のとおりです。装飾された関数をインポートするとどうなりますか?なぜこれは機能しませんか?

答えて

2

これは、import mainがメインファイルの新しいインスタンスを作成するためです。これを確認する簡単な方法は、次のコードです:

>>> sys.modules['main'] == sys.modules['__main__'] 
False 

一つの解決策は、from __main__ import handlefrom main import handleを変更することです。 (これは、main.pyファイルがプログラムを開始するファイルであることに注意してください。)dynimpをインポートする前に、別の回避策をsys.modules['main'] = sys.modules['__main__']に設定します。

関連する問題