Python 模塊相對引用


文件結構如下

python_directory/
├── __init__.py
└── app
    ├── __init__.py
    ├── sub1
    │   ├── __init__.py
    │   └── mod1.py
    └── sub2
        ├── __init__.py
        ├── mod2.py

除了 mod1.py,其他文件內容都為空。

mod1.py

print('__name__: {}'.format(__name__))
print('__package__: {}'.format(__package__))
from ..sub2 import mod2
print('Import Successfully!')

如果 __package__ 不為空,相對引用會根據 __package__ 而不是 __name__[2]。

Relative Import In Non-Package

如果直接執行一個模塊,那么它的 __name____main__。Python 會認為這個模塊是一個最頂層的模塊,而不管這個模塊在文件系統中的實際位置[1]。

$ pwd
/path_to/python_directory

$ python app/sub1/mod1.py 
__name__: __main__
__package__: None
Traceback (most recent call last):
  File "app/sub1/mod1.py", line 3, in <module>
    from ..sub2 import mod2
ValueError: Attempted relative import in non-package

一個最頂層的模塊 -- 我理解為 Python 把這個模塊復制到在一個單獨的目錄中然后再執行,由於該目錄下只有這個一個模塊,
所以它不是一個 package。

Beyond Top Level Package

$ pwd
/path_to/python_directory/app

$ python -m sub1.mod1
__name__: __main__
__package__: sub1
Traceback (most recent call last):
  File "/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 174, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/path_to/python_directory/app/sub1/mod1.py", line 4, in <module>
    from ..sub2 import mod2
ValueError: Attempted relative import beyond toplevel package

由於 -m sub1.mod1,Python 將 package 的頂層視為 sub1,而 ..sub2 位於 app/,超過了當前的最頂層 sub1,所以報錯。

└── app
    ├── __init__.py
    ├── sub1
    │   ├── __init__.py
    │   └── mod1.py
    └── sub2

正確的調用

$ pwd
/path_to/python_directory

$ python -m app.sub1.mod1
__name__: __main__
__package__: app.sub1
Import Successfully!

此時 ..sub2 相當於 app.sub2

參考

  1. PEP 328 -- Imports: Multi-Line and Absolute/Relative
  2. PEP 366 -- Main module explicit relative imports


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM