find_module
和load_module
都被棄用。您需要分別切換到find_spec
和(create_module
和exec_module
)模塊。有關詳細信息,請參閱importlib
documentation。
您還需要檢查是否要使用MetaPathFinder
或PathEntryFinder
作爲調用它們的系統是不同的。也就是說,元路徑搜索器首先進入並可以覆蓋內置模塊,而路徑入口搜索器專門用於在sys.path
上找到的模塊。
以下是一個非常基本的進口商,試圖取代整個進口機械。它顯示如何使用這些功能(find_spec
,create_module
和exec_module
)。
import sys
import os.path
from importlib.abc import Loader, MetaPathFinder
from importlib.util import spec_from_file_location
class MyMetaFinder(MetaPathFinder):
def find_spec(self, fullname, path, target=None):
if path is None or path == "":
path = [os.getcwd()] # top level import --
if "." in fullname:
*parents, name = fullname.split(".")
else:
name = fullname
for entry in path:
if os.path.isdir(os.path.join(entry, name)):
# this module has child modules
filename = os.path.join(entry, name, "__init__.py")
submodule_locations = [os.path.join(entry, name)]
else:
filename = os.path.join(entry, name + ".py")
submodule_locations = None
if not os.path.exists(filename):
continue
return spec_from_file_location(fullname, filename, loader=MyLoader(filename),
submodule_search_locations=submodule_locations)
return None # we don't know how to import this
class MyLoader(Loader):
def __init__(self, filename):
self.filename = filename
def create_module(self, spec):
return None # use default module creation semantics
def exec_module(self, module):
with open(self.filename) as f:
data = f.read()
# manipulate data some way...
exec(data, vars(module))
def install():
"""Inserts the finder into the import machinery"""
sys.meta_path.insert(0, MyMetaFinder())
下一個稍微更微妙的版本,試圖重用更多的進口機械。因此,您只需要定義如何獲取模塊的來源。
import sys
from os.path import isdir
from importlib import invalidate_caches
from importlib.abc import SourceLoader
from importlib.machinery import FileFinder
class MyLoader(SourceLoader):
def __init__(self, fullname, path):
self.fullname = fullname
self.path = path
def get_filename(self, fullname):
return self.path
def get_data(self, filename):
"""exec_module is already defined for us, we just have to provide a way
of getting the source code of the module"""
with open(filename) as f:
data = f.read()
# do something with data ...
# eg. ignore it... return "print('hello world')"
return data
loader_details = MyLoader, [".py"]
def install():
# insert the path hook ahead of other path hooks
sys.path_hooks.insert(0, FileFinder.path_hook(loader_details))
# clear any loaders that might already be in use by the FileFinder
sys.path_importer_cache.clear()
invalidate_caches()
如果你看看'imp.new_module'文檔,你會發現'從3.4版開始棄用:使用types.ModuleType來代替。'這不能解決你的問題嗎? –
我看到imp.modules必須以這種方式替換,但文檔指示使用module_from_spec(來自importlib)。我使用imp中的3個方法來執行自定義鉤子導入程序,並且需要找到importlib的等效項。 –