Python導入メカニズム-import hook


Python import hookはPythonプローブに翻訳できます.その実現原理は以下のいくつかの知識点に関連している:1.Python導入プロトコル2.sys.meta_path
一、PythonインポートプロトコルPythonのメモリにロードされたすべてのモジュールはsysに置かれる.modules.モジュールが1つある場合は、まずこのリストでモジュールがロードされているかどうかを検索します.ロードされている場合は、モジュールの名前を呼び出しているモジュールのLocal名前空間に追加するだけです.ロードされていない場合はsysから.pathディレクトリではモジュール名に従ってモジュールファイルを検索し、モジュールファイルはpy、pyc、pydであり、見つけたらモジュールをメモリにロードしsysに追加する.modulesでは、指定モジュールがsysにない場合が一般的です.modulesで見つかり、Pythonのインポートプロトコルを呼び出してモジュールを検索およびロードします.pythonインポートプロトコルメカニズムは、ルックアップfinderとローダloaderで構成されます.ルックアップfinderの役割は、指定したモジュールを見つけ、実際のインポート動作を処理するローダを提供することです.検索器を登録するにはsys.path_hooksリストにあります.ルックアップはモジュールを実際にロードしません.指定されたモジュールを見つけることができれば、モジュールは関連情報のパッケージをインポートし、モジュールをロードするときにメカニズムが運用する情報をインポートするモジュールブランチを返します.Finderオブジェクトfinderは、次のfind_を実装する必要があります.moduleメソッド:finder.find_module(fullname,path=None)1•finderがmeta_に読み込まれた場合path、この方法は2番目のパラメータを受け入れます.•Importが最上位モジュールである場合:None、•importがサブモジュールまたはサブパッケージである場合:PATH•モジュールを見つけてloaderオブジェクトを返す必要がある場合、Noneローダloaderに戻る必要がある場合は、次のload_を実現する必要があります.moduleメソッドloader.load_module(fullname):•この関数はロードされたモジュールを返すか、異常を投げ出すか•転送されたfullnameがsysにあるかどうかを判断する.modulesでは、loaderがロードしたモジュールを使用する必要があります.そうしないと、reload機能が正常に動作しません.fullnameがsysにない場合.modulesでは、loaderがmoduleを新規作成してロードする必要があります•Loaderがインポートするモジュールコードを実行する前に、モジュールがsysにインポートされている必要があります.modulesで、そうでないと無限反復を引き起こす•インポートに失敗した場合、loaderはsysに挿入されたことをクリアする必要があります.modulesのモジュールは、このようなルックアップとローダフックを含むプログラムを自分で実現することでpythonのインポート動作の制御を実現し、Pythonロードモジュールの機能を拡張することができる.
二.sys.meta_path pythonモジュールはimportで参照され、from package import module as mymoduleコマンドの行を実行すると、Python解釈器はpackageというパッケージのmoduleモジュールを検索し、mymoduleとして現在のワークスペースに導入します.import文は主に2つのことをしました.対応するmoduleを検索し、local namespaceにmoduleをロードします.importの最初の段階では、主にモジュールを導入する機能を検索することが完了し、この検索の過程は以下の通りである:1.チェックするmodulesリスト(以前のimportのクラスライブラリのキャッシュが保存されている)は、moduleが見つかった場合、2番目のステップに進みます.2.検査sys.meta_pathリスト.meta_pathはlistで、3.いくつかの暗黙的なfinderオブジェクトをチェックし、異なるpython実装には異なる暗黙的なfinderがあるがsysがある.path_hooks, sys.path_importer_cacheとsys.path. 4.ImportErrorを投げ出す上記の過程から分かるように、import関連の操作を実行するとsysがトリガーされる.meta_pathリストで定義されたfinderオブジェクト.Pythonインポートプロトコルのルールに従って、finderオブジェクトとloaderオブジェクトに対応するfind_を実装するだけでimport hookを実装する必要があります.moduleメソッドとload_moduleメソッド.Pythonインタプリタimportモジュールのときにこのfinderオブジェクトをトリガーするには、このオブジェクトのインスタンスをsysに挿入するだけです.metapathリストにあります.
次は簡単なhellp worldプログラムです.私たちはimport hookを通じてモジュールをロードするときに検索とロードの情報を印刷します.
import sys

class MetaPathFinder:

    def find_module(self, fullname, path=None):
        print('find_module {}'.format(fullname))
        return MetaPathLoader()


class MetaPathLoader:

    def load_module(self, fullname):
        print('load_module {}'.format(fullname))
        sys.modules[fullname] = sys
        return sys

sys.meta_path.insert(0, MetaPathFinder())

if __name__ == '__main__':
    import http
    print(http)
    print(http.version_info)

load_moduleメソッドは、importのmoduleオブジェクトであるmoduleオブジェクトを返します.例えば私は上のようにhttpをsysというmoduleに置き換えました.
$ python meta_path1.py
find_module http
load_module http
'sys' (built-in)>
sys.version_info(major=3, minor=5, micro=1, releaselevel='final', serial=0)