2016-09-09 11 views
2

私はPython 3で "インポートフック"を実装しようとしています。フックはインポートされるすべてのクラスに属性を追加することになっています。 (そうでもないすべてのクラスが、問題を単純化のために、のはそうと仮定しましょう。)Python 3のインポートフック

私のように定義されたローダーを持って、次のとおりです。

import sys 

class ConfigurableImports(object): 

    def find_module(self, fullname, path): 
     return self 

    def create_module(self, spec): 
     # ??? 

    def exec_module(self, module): 
     # ??? 

sys.meta_path = [ConfigurableImports()] 

ドキュメントはローダー、3.6のようということを述べてcreate_moduleexec_moduleの両方を実装する必要があります。しかし、ドキュメントには、これらを実装するために何をすべきか、また例は何も示されていません。 Pythonモジュールをロードするだけなので、私のユースケースは非常に簡単です。ローダーの振る舞いは、デフォルトの振る舞いとほぼ同じです。

私は、私はちょうどimportlib.import_moduleを使用し、それに応じてモジュールの内容を変更したいことができれば、しかし、importlibはインポートフックを利用するので、無限の再帰を得ます。

EDIT:impモジュールのload_moduleも試してみましたが、これは推奨されていません。

インポートフックでこの機能を実装する方法は簡単ですか、それとも間違った方法ですか?

+0

を取得する必要がある場合

だから、あなたはそれを呼び出すことができます私はここで興味深い例が見つかりました:のhttp://chimera.labs.oreilly.com/books/1230000000393/ch10.html#_solution_179 – Tom

+0

私の読書exec_moduleとcreate_moduleを実装する必要はありませんが、exec_moduleだけを実装することはできません。それはどちらかまたは両方です。 Create_moduleはNoneを返します –

答えて

1

Imhoは、モジュールを変更するだけで、モジュールが見つかって読み込まれた後に再生する必要がある場合、モジュールを見つけてロードして返すフックを実際に作成する必要はありません。ちょうどパッチ__import__。これは、数行で簡単に行うことができます

ここ
import builtins 
from inspect import getmembers, isclass 

old_imp = builtins.__import__ 

def add_attr(mod): 
    for name, val in getmembers(mod): 
     if isclass(val): 
      setattr(val, 'a', 10) 

def custom_import(*args, **kwargs): 
    m = old_imp(*args, **kwargs) 
    add_attr(m) 
    return m 

builtins.__import__ = custom_import 

__import__がロードされたモジュールを取得するには、元の__import__を呼び出し、実際にない機能add_attrを呼び出して、カスタムインポートによって置き換えられますモジュール内のクラスの変更(getmembersisclassからinspectへ)もちろん

これは、スクリプトをimportとき、変更が行われるような方法で作成されます。

あなたは、おそらくrestore補助関数を作成する必要がありますなど必要なすなわち物事場合は、再度それを変更することができます。

def revert(): builtins.__import__ = old_imp 

def apply(): builtins.__import__ = custom_import 

コンテキストマネージャは、あまりにもクールに加えかもしれません。あなたは

+0

興味深いアイデア、Jim!私はそれを試してみましょう。これはとにかく簡単な解決策に見えます。 (これまでのインポートフックで「正しい方法」を実行しようとすると、24時間を費やして何も達成できなくなりました!) – Tom