2013-03-25 74 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()]))