簡體   English   中英

如何解決這些相對導入錯誤

[英]How can I fix these relative import error

我有這樣的文件夾結構,每次嘗試使用相對導入時,都會引發錯誤

├── graphics
│   ├── __init__.py
│   ├── A
│   │   ├── __init__.py
│   │   ├── grok.py
│   │   └── spam.py
    └── B
        ├── __init__.py
        └── bar.py


spam.py/
    def func():
        pass
bar.py/
    def f():
        pass

所有這些代碼都在grok.py中進行了測試:

from . import spam
# ImportError: cannot import name 'spam'

from .spam import func
# ModuleNotFoundError: No module named '__main__.spam'; '__main__'     
is not a package

from ..B import bar
# ValueError: attempted relative import beyond top-level package

以下代碼均不會導致任何錯誤:

from graphics.A import spam
from graphics.A.spam import func
from graphics.B import bar
from graphics.B.bar import f

我假設當您說“ 在grok.py中測試 ”時,您正在像這樣運行它:

python3 graphics/A/grok.py
python3 A/grok.py
python3 grok.py

從Python關於PackagesPackage-In-Package引用的文檔中 ,有一條注釋指出:

請注意,相對導入基於當前模塊的名稱。 由於主模塊的名稱始終為“ __main__ ”,因此用作Python應用程序主模塊的模塊 必須始終使用絕對導入

當您運行grok.py ,它將被視為主模塊,並且只有在您使用絕對導入的情況下,導入才起作用(假設您未對sys.path進行任何更改,我們將在以后進行介紹)。 您可以通過將print(__name__)放在print(__name__)的開頭來進行測試,這將打印出“ __main__ ”。

如果在調用grok模塊的圖形包下有一個單獨的python文件(例如main.py ),則相對導入實際上將起作用。

├── graphics
│   ├── __init__.py
|   ├── main.py     <<---- add this
│   ├── A
│   ├── B

main.py ,讓我們只導入grok模塊:

from A import grok

grok.py ,讓我們測試相對導入:

from . import spam
spam.spam_func()

from .spam import spam_func
spam_func()

from B import bar
bar.bar_func()

spam.py

def spam_func():
    print("spammy")

bar.py

def bar_func():
    print("barry")

當您運行main.py

graphics$ python3 main.py
spammy
spammy
barry

您不會遇到任何先前的錯誤。 相對進口工作。 注意,要從B導入,我from B而不是from ..B 這是因為導入路徑是從main.py的角度來看的。 您可以通過在main.py頂部添加以下內容來進行測試:

import sys
print(sys.path)
# prints a list, ['/path/to/graphics/',...]

如果您from ..B ,則意味着/path/to/graphics/../當然沒有B模塊(因此,您將收到“ 嘗試在頂級軟件包之外進行相對導入 ”錯誤)


現在,假設您不想使用單獨的main.py ,而是要直接運行grok.py 您可以手動將graphics包的路徑添加到sys.path 然后,您可以from A grok.py from Afrom B中進行grok.py

import sys
sys.path.append("/full/path/to/graphics/")

from A import spam
spam.spam_func()

from B import bar
bar.bar_func() 

如果您想“入侵” sys.path ,建議您閱讀更多有關sys.path並查看其他相關文章,以討論sys.path添加路徑的sys.path

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM