17.2.6.11 元路径
sys.meta_path进一步扩展了可能的导入来源,允许在扫描常规的sys.path之前先搜索查找工具。元路径上查找工具的API与常规路径上查找工具的API是一样的,只不过元查找工具不限于sys.path中的一项,它可以搜索任何地方。
import sys
import imp
class NoisyMetaImportFinder:
def __init__(self,prefix):
print('Creating NoisyMetaImportFinder for {}'.format(
prefix))
self.prefix = prefix
return
def find_module(self,fullname,path=None):
print('looking for {!r} with path {!r}'.format(
fullname,path))
name_parts = fullname.split('.')
if name_parts and name_parts[0] == self.prefix:
print('... found prefix, returning loader')
return NoisyMetaImportLoader(path)
else:
print('... not the right prefix, cannot load')
return None
class NoisyMetaImportLoader:
def __init__(self,path_entry):
self.path_entry = path_entry
return
def load_module(self,fullname):
print('loading {}'.format(fullname))
if fullname in sys.modules:
mod = sys.modules[fullname]
else:
mod = sys.modules.setdefault(
fullname,
imp.new_module(fullname))
# Set a few properties required by PEP 302.
mod.__file__ = fullname
mod.__name__ = fullname
# Always looks like a package
mod.__path__ = ['path-entry-goes-here']
mod.__loader__ = self
mod.__package__ = '.'.join(fullname.split('.')[:-1])
return mod
# Install the meta_path finder.
sys.meta_path.append(NoisyMetaImportFinder('foo'))
# Import some modules that are "found" by the meta-path finder.
print()
import foo
print()
import foo.bar
# Import a module that is not found.
print()
try:
import bar
except ImportError as e:
pass
搜索sys.path之前,会询问元路径上的各个查找工具,所以总算可以让一个中心导入工具加载模块,而不必显式地修改sys.path。一旦"找到"模块,加载工具API就会像常规加载工具一样正常工作(不过为简单起见,这个例子有所删减)。