find_module
und load_module
sind beide veraltet. Sie müssen zu find_spec
und (create_module
und exec_module
) Modul jeweils wechseln. Einzelheiten finden Sie unter importlib
documentation.
Sie müssen auch prüfen, ob Sie eine MetaPathFinder
oder eine PathEntryFinder
als System verwenden möchten, um sie aufzurufen ist anders. Das heißt, der Metapathfinder geht zuerst und kann eingebaute Module überschreiben, während der Pfadeintragsfinder speziell für Module funktioniert, die unter sys.path
gefunden werden.
Das folgende ist ein sehr einfacher Importeur, der versucht, die gesamte Importmaschinerie für zu ersetzen. Es zeigt, wie die Funktionen (find_spec
, und exec_module
) zu verwenden sind.
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())
Als nächstes ist eine etwas empfindlichere Version, die versucht, mehr der Import-Maschinen wiederzuverwenden. Daher müssen Sie nur definieren, wie die Quelle des Moduls abgerufen werden soll.
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()
Wenn Sie einen Blick auf die 'imp.new_module' Dokumentation nehmen, werden Sie' finden Veraltet seit Version 3.4: Verwenden Sie types.ModuleType instead.' Ist das Ihr Problem nicht lösen? –
Ich sah, dass imp.module auf diese Weise ersetzt werden mussten, aber die Dokumentation zeigt an, dass module_from_spec (von importlib) verwendet werden soll. Ich benutze 3 Methoden von imp, um einen benutzerdefinierten Hook-Importer zu machen und finde das Äquivalent für importlib. –