2013-03-25 79 views
2

我试图重新实施一些基于imp模块的代码,以替代使用importlib。还有就是功能imp.find_moduleimportlib.find_loader之间细微的差别:如何强制importlib find_loader专门使用特定路径?

# Using imp find_module 
>>> import imp 
>>> imp.find_module("abc", ["some/path/module.py"]) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib64/python3.3/imp.py", line 220, in find_module 
    raise ImportError(_bootstrap._ERR_MSG.format(name), name=name) 
ImportError: No module named 'abc' 

# Using import find_loader 
>>> import importlib 
>>> loader = importlib.find_loader("abc", ["some/path/module.py"]) 
>>> loader.path 
'/usr/lib64/python3.3/abc.py' 

看起来importlib是回落到系统库,同时imp.find_module是采用独家的方式path参数,这最终引发异常。

如何强制importlib.find_loader专门使用特定路径?

回答

0

我发现答案不是使用find_loader,而是使用importlib.machinery.PathFinder类来查找特定路径中的模块。

1

这取决于您的代码的确切目标是什么。首先,这两个调用都是错误的,因为'path'参数是一个目录列表,而不是特定的文件。

其次,abc从标准库返回,因为它已经在sys.modules中。请记住,importlib.find_loader()会为指定的模块找到加载程序,因此包括查看sys.modules['abc'].__loader__以避免不必要地找到它。如果您在标准库(例如tokenize)中指定了一个尚未导入的模块,那么importlib.find_loader()将返回None。

换句话说,importlib.find_loader()将在'path'中指定的特定目录中搜​​索模块,但是您必须查找尚未导入的内容。

+1

谢谢你的答案,我实际上找到了做我想做的方式。事实是importlib在解析模块名称时使用了meta_path而不是路径。 – 2013-03-28 12:36:02

+0

AttributeError:'模块'对象没有属性'find_loader' – Cerin 2015-04-20 18:17:29

1

我认为您对impimportlib的使用可能不正确。路径列表应该是目录的路径,而不是特定的.py文件。你永远不会在module.py中找到abc.py,所以导入失败。

例如我在本地pip.py文件中定义了一些自定义Fabric pip功能,但我也想在我的站点包目录中加载官方pip.py。由于我第一次使用importlib导入我的自定义pip.py,这使得import pip加载我的自定义版本。要加载模块在网站包,我必须做的:

from distutils.sysconfig import get_python_lib 
import imp 
real_pip = imp.load_module('pip', *imp.find_module('pip', [get_python_lib()]))