[英]The way to make namespace packages in Python
從分布式的命名空間包中 ,我知道我可以利用命名空間包將一個大的Python包分成幾個較小的包。 真的很棒。 該文件還提到:
順便提一下,請注意,在正常的Python包布局中,項目的源樹必須包含命名空間包'__init__.py文件(以及任何父包的__init__.py)。 這些
__init__
.py文件必須包含以下行:__import__('pkg_resources').declare_namespace(__name__)
此代碼確保命名空間包機制正在運行,並且當前包已注冊為命名空間包。
我想知道將相同的目錄層次結構保存到包的層次結構有什么好處嗎? 或者,這只是distribute / setuptools的命名空間包功能的技術要求?
當然,
我想提供一個子包foo.bar ,這樣我就必須構建以下文件夾層次結構並准備__init__.py以使setup.py工作在命名空間包中:
~foo.bar/
~foo.bar/setup.py
~foo.bar/foo/__init__.py <= one-lined file dedicated to namespace packages
~foo.bar/foo/bar/__init__.py
~foo.bar/foo/bar/foobar.py
我不熟悉命名空間包,但它在我看來1)foo / bar和2)(幾乎)單行__init__.py是例行任務。 它們確實提供了一些“這是命名空間包”的提示,但我認為我們已經在setup.py中提供了這些信息?
編輯:
如下面的塊所示,我可以在我的工作目錄中使用沒有該嵌套目錄和單行__init__.py的命名空間包嗎? 也就是說,我們可以通過只設置一行namespace_packages = ['foo']
來請求setup.py自動生成這些嗎?
~foo.bar/
~foo.bar/setup.py
~foo.bar/src/__init__.py <= for bar package
~foo.bar/src/foobar.py
在導入子包時,命名空間包主要具有特定的效果。 基本上,這是導入foo.bar
時發生的情況
sys.path
,查找看起來像foo
東西。 foo
里面的bar
。 bar
:
foo
是普通包,則會引發ImportError
,表明foo.bar
不存在。 foo
是命名空間包,則導入器會返回查看sys.path
以查找foo
的下一個匹配項。 只有在所有路徑都已耗盡時才會引發ImportError
。 這就是它的作用 ,但並沒有解釋為什么你會這么想。 假設你設計了一個很大的,有用的庫( foo
),但作為其中的一部分,你還開發了一個小但非常有用的實用程序( foo.bar
),其他python程序員發現它很有用,即使它們沒有用於更大的圖書館
您可以將它們一起分發為一個包的大塊(就像您設計的那樣),即使大多數使用它的人只會導入子模塊。 你的用戶會發現這非常不方便,因為他們必須下載整個東西(所有200MB!),即使他們真的只對10行實用程序類感興趣。 如果你有一個開放的許可證,你可能會發現有幾個人最終要求它,現在你的實用程序模塊有六個不同版本。
您可以重寫整個庫,以便實用程序位於foo
命名空間之外(只是bar
而不是foo.bar
)。 您將能夠單獨分發該實用程序,並且您的一些用戶會很高興,但這是很多工作,特別是考慮到實際上有很多用戶使用整個庫,因此他們將不得不重寫他們的程序使用新的。
所以你真正想要的是一種foo.bar
安裝foo.bar
的方法,但是當你想要的時候也很樂意與foo
共存。
命名空間包允許這兩個完全獨立的foo
包安裝可以共存。 setuptools
會認識到這兩個包被設計成彼此相鄰並禮貌地移動文件夾/文件,使得它們都在路徑上並顯示為foo
,一個包含foo.bar
而另一個包含其余的foo
。
你將有兩個不同的setup.py
腳本,每個腳本一個。 兩個包中的foo/__init__.py
必須指示它們是命名空間包,因此無論首先發現哪個包,導入器都知道繼續。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.