2013-02-28 96 views
2

我有一個名爲tokenize.py的本地模塊,掩蓋了一個同名的標準庫模塊。當我試圖導入一個外部模塊(sklearn.linear_model)時,我只發現了這一點,而這個模塊又是import tokenize,並且期望獲得標準庫模塊,而是獲取我的本地模塊。當本地模塊屏蔽由外部模塊導入的標準庫模塊時,如何導入外部模塊?

這與How to access a standard-library module in Python when there is a local module with the same name?有關,但設置不同,因爲應用上述解決方案需要修改外部模塊。

一個選項是重命名本地tokenize.py,但我不希望這樣做,因爲「標記化」最能表達模塊的角色。

爲了說明問題,這裏是模塊結構的草圖:

 
    \my_module 
     \__init__.py 
     \tokenize.py 
     \use_tokenize.py 

在use_tokenize.py,有以下導入:

import sklearn.linear_model 

這將導致以下錯誤,當調用python my_module/use_tokenize.py

Traceback (most recent call last): 
    File "use_tokenize.py", line 1, in <module> 
    import sklearn.linear_model 
    <...> 
    File "<EDITED>/lib/python2.7/site-packages/sklearn/externals/joblib/format_stack.py", line 35, in <module> 
    generate_tokens = tokenize.tokenize 
AttributeError: 'module' object has no attribute 'tokenize' 

有什麼辦法可以抑制本地模塊當導入一個外部模塊?

編輯:新增python2.7作爲標記由於意見,解決方案由Python版本而異

+0

您正在使用哪個版本的Python?規則和解決方法是不同的。 – abarnert 2013-02-28 00:47:01

+2

但實際上,您應該重命名您的本地'tokenize.py'。在所有數百個腳本和模塊中自動修復所有'import tokenize'和'tokenize.'的腳本應該需要幾分鐘的時間才能寫入並運行幾秒鐘... – abarnert 2013-02-28 00:48:21

+0

如果創建一個具有相同名稱的模塊作爲一個標準庫模塊,沒有人可以在不隱藏標準庫模塊的情況下安裝庫。解決方案是不給你的模塊這個名字。 (如果它是包的一部分,你仍然可以擁有'tokenize.py',因爲在這種情況下,一個簡單的'import tokenize'將不會看到它。) – BrenBarn 2013-02-28 01:02:55

回答

3

的問題是沒有這麼多的模塊名稱,但你正在運行一個模塊喜歡它是一個腳本。當Python運行腳本時,它會將腳本的包含目錄添加爲sys.path中的第一個元素,因此所有來自任何位置的模塊查找都將首先搜索該目錄。

爲了避免這種情況,請Python來執行它作爲一個模塊來代替:

python -m my_module.use_tokenize 

或者,當然,你可以只保留可執行腳本你的模塊層次。

0

解釋器搜索模塊的路徑列於sys.path中。爲防止第三方模塊在導入時看到本地模塊,我們從路徑中刪除.

import sys 
sys.path = sys.path[1:] 
import sklearn.linear_model #using the original example. 

然而,這不會如果本地tokenize已經導入工作,這也將防止本地tokenize被進口的,即使我們恢復舊sys.path如下:這可以通過以下方式實現:

import sys 
old_path = sys.path 
sys.path = sys.path[1:] 
import sklearn.linear_model #using the original example. 
sys.path = old_path 

這是因爲Python解釋保持的導入模塊內部的映射,以便稍後對同一模塊請求被從該映射實現。這種映射對解釋器是全局的,所以import tokenize從運行它的任何代碼返回相同的模塊 - 這正是我們試圖改變的行爲。爲了實現這一點,我們必須改變這種映射。最簡單的方法是簡單地刪除sys.modules中的相關條目。

import sys 
old_path = sys.path 
sys.path = sys.path[1:] 
import sklearn.linear_model #using the original example. 
sys.path = old_path 
del sys.modules['tokenize'] #get of the mapping to the standard library tokenize 
import tokenize #cause our local tokenize to be imported