2017-03-18 7 views
-1

他の外部パッケージからモジュールをインポートせずにパッケージを深くリロードするにはどうすればよいですか?次のリロードのために例えばディープリロードモジュールは1つのパッケージからのみ

、:

# example_pkg.py 
import logging # do not reload this stdlib package 
import example_pkg.ex_mod # reload this module 

IPythonのdeepreloadモジュールは、輸入のためのホワイトリストを指定し、スレッド環境のために、それは信頼できない可能リロード時にモジュールレベルの変数を使用することはできません。

beforeと似たような質問がありましたが、それは単一パッケージ内での排他的ではなく依存関係の発見に焦点を当てていました(コメント内でmentioned)。

答えて

0

モジュールとimportlibモジュールを使用すると、Pythonのインポートキャッシュからパッケージとそのモジュールを削除する関数を書くことができます。これにより、パッケージが再インポートされたときに子モジュールを再ロードすることができます。

import sys 
import importlib 
from types import ModuleType 

def deep_reload(m: ModuleType): 
    name = m.__name__ # get the name that is used in sys.modules 
    name_ext = name + '.' # support finding sub modules or packages 
    del m 

    def compare(loaded: str): 
     return (loaded == name) or loaded.startswith(name_ext) 

    all_mods = tuple(sys.modules) # prevent changing iterable while iterating over it 
    sub_mods = filter(compare, all_mods): 
    for pkg in sub_pkgs: 
     del sys.modules[pkg] # remove sub modules and packages from import cache 

    return importlib.import_module(name) 

このコードは、同様に、それはスレッドセーフにするためにLockで拡張することができます。

from threading import Lock 

sys_mod_lock = Lock() # all accesses to sys.modules must be programmed to acquire this lock first 
# this means do not use any builtin import mechanism such as the 'import' statement once the following function is being used 
# instead use importlib's import_module function while sys_mod_lock is acquired 

def tsafe_reload(m: ModuleType): 
    with sys_mod_lock: 
     return deep_reload(m) 

注:これらの関数は標準ライブラリのreloadからの警告の1が付属しています。古いパッケージにつながっているプログラム内の他の参照は維持され、自動的には置き換えられません。そのためには、globalsubを見れば、インタプリタ内のオブジェクトへのすべての参照を別のオブジェクトに置き換えることができます(通常はデバッグ用です)。

関連する問題