簡體   English   中英

Python中“__package__”屬性的目的是什么?

[英]What's the purpose of the “__package__” attribute in Python?

我想知道的是__package__究竟什么意思 在官方文件中沒有找到任何解釋,即使是在SO上。

如果你能提供一些例子,我會非常高興。

請參閱PEP 366導入系統參考文檔

主要的建議更改是引入新的模塊級屬性__package__ 如果存在,相對導入將基於此屬性而不是模塊__name__屬性。

  • 應該設置模塊的__package__屬性。 它的值必須是一個字符串,但它可以是與__name__相同的值。 如果該屬性設置為“ None或缺少,則導入系統將使用更合適的值填充該屬性。 當模塊是包時,其__package__值應設置為__name__ 當模塊不是包時, __package__設置為頂級模塊的空字符串,或子模塊的空字符串,設置為父包的名稱。 有關詳細信息,請參閱PEP 366

因此,對於位於模塊foo/bar/baz.py__name__設為foo.bar.baz ,並__package__設置為foo.bar ,而foo/bar/__init__.py將有foo.bar同時為__name____package__屬性。

我想知道的是__package__究竟是什么意思

它是實現顯式相對導入的機制。

__package__有三種可能的值類別

  • 包名(字符串)
  • 一個空字符串
  • 沒有

包裹名字

也就是說,如果模塊位於包中,則__package__將設置為包名稱以啟用顯式相對導入。 特別:

當模塊是包時,其__package__值應設置為__name__ 當模塊不是包時,應將子模塊的__package__設置為父包的名稱。

空字符串

如果模塊位於root或top級別,即導入當前模塊

import current_module

或者當頂級模塊作為入口點運行時,如下所示:

$ python -m current_module

那么__package__是一個空字符串。 或者正如文檔所說

當模塊不是包時, __package__應該設置為頂級模塊的空字符串...

沒有

如果模塊/腳本由filename運行, __package__為None

當主模塊由其文件名指定時, __package__屬性將設置為None。

證據

首先,讓我們使用Python 3.6創建一個帶有嘈雜調試的文件結構:

text = "print(f'{__name__}, __file__: {__file__}, __package__: {repr(__package__)}')"

from pathlib import Path
Path('foo.py').write_text(text)
Path('package').mkdir()
Path('package/__init__.py').write_text(text)
Path('package/__main__.py').write_text(text)
Path('package/bar.py').write_text(text)

# and include a submodule with a relative import:
Path('package/baz.py').write_text(text + '\nfrom . import bar')

現在我們看到作為模塊執行的foo.py具有__package__的空字符串,而由文件名作為入口點執行的腳本具有None

$ python -m foo
__main__, __file__: ~\foo.py, __package__: ''
$ python foo.py
__main__, __file__: foo.py, __package__: None

當我們執行一個包作為入口點的模塊時,它的__init__.py模塊運行,然后它的__main__.py運行:

$ python -m package
package, __file__: ~\package\__init__.py, __package__: 'package'
__main__, __file__: ~\package\__main__.py, __package__: 'package'

類似地,當我們執行子模塊作為入口點的模塊時,運行__init__.py模塊,然后運行:

$ python -m package.bar
package, __file__: ~\package\__init__.py, __package__: 'package'
__main__, __file__: ~\package\bar.py, __package__: 'package'

最后,我們看到顯式相對導入,具有__package__的完整原因(在此處發生)將啟用:

$ python -m package.baz
package, __file__: ~\package\__init__.py, __package__: 'package'
__main__, __file__: ~\package\baz.py, __package__: 'package'
package.bar, __file__: ~\package\bar.py, __package__: 'package'

注意,在輸出中,我已經用~替換了父目錄。

暫無
暫無

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

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