[英]Python Imports failing. Relative imports, package recognition, __init__.py , __package__, __all__
我一直在閱讀很多線程,與此問題相關的 PEP 文章,大約有 4 篇,但沒有一篇文章在某些方面給出了明確的想法,我仍然無法進行相對導入。
事實上,我的主包的內容根本沒有列出。
再版。 我修改了所有帖子,它太復雜了,問題很多。
在C:/test/
我有這個包:
Package/ (FOLDER 2)
__init__.py
moduleA.py
moduleB.py
moduleA
導入moduleB
,反之亦然。__init__.py
為空我的流程:
C:/test/
添加到sys.path
。import Package
(WORKS)dir(Package)
不列出包內的任何模塊。<module 'Package' from C:/test/Package/_init_.py>
__file__
是 Package 下的 init 文件__name__
是Package
__package__
是一個空字符串__path__
是C:/test/Package
測試 1 - 版本 1:在moduleA
我有from Package import moduleB
我明白了:
>>> import Package.moduleA
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:/test\Package\moduleA.py", line
from Package import moduleB
File "C:/test\Package\moduleB.py", line
from Package import moduleA
ImportError: cannot import name moduleA
它不起作用,因為moduleA
不是Package
一部分。 所以Package
不被識別為包?
測試 1 - 版本 2:在moduleA
我from . import moduleB
from . import moduleB
不行,同樣的錯誤
測試 1 - 版本 3:在moduleA
我import Package.moduleB
有用。
之后,運行:
>>> dir(Package.moduleB)
['Package', '__builtins__', '__doc__', '__file__', '__name__', '__package__']
>>> Package.moduleB.Package
<module 'Package' from 'C:/prueba\Package\__init__.py'>
>>> dir(Package)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', 'moduleA', 'moduleB']
所以現在, Package.moduleB
將Package
作為變量 令人驚訝的是, Package
看起來像一個合適的包,並且包含兩個模塊。
事實上,在版本 1 和版本 2 中執行任何導入現在都可以工作,因為現在moduleA
和moduleB
是Package
一部分。
問題:
1) 為什么Package
不被識別為包? 是嗎? 它不應該包含所有子模塊嗎?
2) 為什么運行import Package.moduleA
在moduleA
生成Package
?
3) 為什么運行import Package.moduleA
會將moduleA
添加到Package
而它之前沒有?
4) 空的__init__.py
文件和非空的__init__.py
文件對此有影響嗎?
5) 定義一個包含['moduleA', 'moduleB']
的__all__
變量在這里有什么作用嗎?
6) 如何使 init 文件加載兩個子模塊? 我應該在里面import Package.moduleA
和Package.moduleB
嗎?...我不能像import .moduleA as moduleA
或類似的東西那樣做嗎? (如果Package
的名稱發生變化怎么辦?)
7) 包變量上的空字符串有影響嗎? 如果我們想讓它識別自己,我們應該更改它的內容...... __package__
應該與__name__
相同,或者這就是 PEP 所說的。 但是這樣做沒有用:
if __name__ == "__main__" and __package__ is None:
__package__ = "Package"
這是一個循環依賴問題。 它與此問題非常相似,但不同之處在於您嘗試從包中導入模塊,而不是從模塊中導入類。 在這種情況下,最好的解決方案是重新考慮您的代碼,以便不需要循環依賴。 將任何常用函數或類移出包中的第三個模塊。
擔心__package__
是一個紅鯡魚。 當你的包成為一個合適的包時,python 導入系統會適當地設置它。
問題是moduleA
和moduleB
僅在成功導入后才放入package
。 但是,由於moduleA
和moduleB
都在導入過程中,因此它們在package
無法看到彼此。 當您繞過相對導入機制時,絕對導入部分解決了問題。 但是,如果您的模塊在初始化期間需要彼此的一部分,則程序將失敗。
如果var = ...
行被刪除,以下代碼將起作用。
包.moduleA
import package.moduleB
def func():
return 1
包.moduleB
import package.moduleA
var = package.moduleA.func() # error, can't find moduleA
包.moduleA
from . import moduleB
def depends_on_y():
return moduleB.y()
def x():
return "x"
包.moduleB
from . import moduleA
def depends_on_x():
return moduleA.x()
def y():
return "y"
包.common
def x():
return "x"
def y():
return "y"
包.moduleA
from .common import y
def depends_on_y():
return y()
包.moduleB
from .common import x
def depends_on_x():
return x()
這是 Python 3.5 之前版本中存在的 Python 錯誤。 請參閱問題 992389 (多年)和問題 17636 ,其中修復了該問題的常見情況。
在 Python 3.5 中修復之后,一個顯式的相對導入,如from . import moduleA
從包內的模塊中from . import moduleA
Package
將在sys.modules
檢入Package.moduleA
,如果moduleA
尚不存在於Package
,則moduleA
。 由於模塊對象在開始加載之前添加到sys.modules
,但直到加載完成后才添加到Package.__dict__
,因此這通常可以解決問題。
使用from package import *
進行循環導入仍然可能存在問題,但在issue 23447 (我為其貢獻了補丁)中,決定修復更模糊的極端情況不值得額外的代碼復雜性。
圓形進口通常是不良設計的標志。 您可能應該將相互依賴的代碼部分重構為一個由其他模塊導入的單個實用程序模塊,或者您應該將兩個單獨的模塊合並為一個。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.