ValueError: attempted relative import beyond top-level package
假設有如下層次包目錄
1 project/ 2 __init__.py 3 mypackage/ 4 __init__.py 5 A/ 6 __init__.py 7 spam.py #* print("In spam") *# 8 grok.py #* print("In grok") *# 9 C/ 10 __init__.py 11 hello.py #* print("In hello") *# 12 B/ 13 __init__.py 14 bar.py #* print("In bar") *# 15 run.py 16 main.py
相對導入語法
from . import module from .. import module from ... import module
相對導入與模塊__name__有關
- run.py作為頂層模塊執行導入A.spam時
- run.py的__name__ 等於 __main__
- spam.py的__name__ 等於 A.spam
- A成為頂層的包,所以相對導入最多只能訪問到A,A之外的層次結構是不可見的
- main.py作為頂層模塊執行導入mypackage.A.spam是
- main.py的 __name__ 為 __main__
- spam.py的__name__ 為 mypackage.A.spam
- mypackage成為頂層包,相對導入作用域擴大,B/包對spam.py可見
相對導入只適用於包中的模塊,頂層的模塊中將不起作用
-
如果將run.py當作頂層執行模塊
-
A/ 和 B/ 將成為 toplevel package 頂層包 A/中的模塊不能用相對導入來導入B/包中的模塊,因為不能越過頂層包。
-
A/、B/ 包中的目錄可以導入本包中及以下的模塊
-
如果將main.py當作頂層執行模塊
-
mypackage/成為頂層包,A/可以訪問到B/包,不會出現 ValueError: attempted relative import beyond top-level package
例子
## run.py (run.py當作頂層執行模塊,即 python run.py) #----------- import A.spam ## spam.py #-------------- from . import grok # ok from .C import hello # ok from ..B import bar # !Err ##—— ValueError: attempted relative import beyond top-level package print('In spam') ## main.py #------------ import mypackage.A.spam ## spam.py #------------- from ..B import bar # ok print('In spam')