モジュールと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
を見れば、インタプリタ内のオブジェクトへのすべての参照を別のオブジェクトに置き換えることができます(通常はデバッグ用です)。