2014-01-23 70 views
3

我注意到其中類似下面的測試失敗一些奇怪的情況:python是否會多次加載模塊?

x = <a function from some module, passed around some big application for a while> 

mod = __import__(x.__module__) 
x_ref = getattr(mod, x.__name__) 
assert x_ref is x # Fails 

(像這樣的代碼出現的泡菜模塊)

我不認爲我有任何進口鉤,重裝電話,或sys.modules操作會混淆python的正常導入緩存行爲。

是否有任何其他原因爲什麼一個模塊會被加載兩次?我見過有關這方面的聲明(例如https://stackoverflow.com/a/10989692/1332492),但我無法通過簡單的獨立腳本重現它。

+0

'assert x_ref == x'說什麼? –

+0

也是假的,但我認爲其實*調用*函數總是給出相同的結果 – ChrisB

+0

這些模塊是否具有'__file__'屬性?測試它們以查看它是否完全相同的模塊。 –

回答

3

我相信你誤解如何__import__作品:

>>> from my_package import my_module 
>>> my_module.function.__module__ 
'my_package.my_module' 
>>> __import__(my_module.function.__module__) 
<module 'my_package' from './my_package/__init__.py'> 

從文檔:

當名稱變量的形式爲package.module,通常情況下, 頂層包(名字直到第一個點)返回,而不是 按名稱命名的模塊。但是,如果給出非空的fromlist 參數,則會返回按名稱命名的模塊。

正如你可以看到__import__返回子模塊,但只有頂部包。如果您還在包級別定義了function,那麼將確實對有不同的參考。

如果你想加載一個模塊,你應該使用importlib.import_module而不是__import__


至於回答您的實際問題:據我所知是沒有辦法導入同一模塊,具有相同名稱,不與進口機制亂搞的兩倍。但是,你可以有一個包的子模塊,這也是在sys.path可用,在您可以進口兩次使用不同的名稱這種情況下:

from some.package import submodule 
import submodule as submodule2 
print(submodule is submodule2) # False. They have *no* relationships. 

有時,這可能會導致問題,例如, pickle。如果您醃製submodule引用的內容,則不能使用submodule2作爲參考將其取消。

但是,這並沒有解決您給我們的具體示例,因爲使用__module__屬性導入應返回正確的模塊。

+0

感謝您的額外信息。我對這個特定的失敗仍然有些迷惑,但我懷疑它與你發佈的最後一段代碼有關 – ChrisB