パーティーに遅れましたが、仲間の旅行者が Python の名前空間パスをたどるのを助けることは決して悪いことではありません!
#1:
では、__init__.py
これらのうちどれを使用する必要がありますか?:
ここにリストされているように、名前空間パッケージを実行する方法は 3 つあります。
ネイティブ名前空間パッケージを使用します。このタイプの名前空間パッケージは PEP 420 で定義されており、Python 3.3 以降で利用できます。これは、名前空間内のパッケージが Python 3 と pip によるインストールのみをサポートする必要がある場合に推奨されます。
pkgutil スタイルの名前空間パッケージを使用します。これは、Python 2 および 3 をサポートする必要がある新しいパッケージと、pip および python setup.py install の両方によるインストールに推奨されます。
pkg_resources スタイルの名前空間パッケージを使用します。この方法は、既にこの方法を使用しているパッケージとの互換性が必要な場合、またはパッケージを zip セーフにする必要がある場合に推奨されます。
#2 ( pkgutil-style
) または #3 ( pkg_resources-style
) を使用している場合は、ファイルに対応するスタイルを使用する必要があり__init__.py
ます。ネイティブ名前空間を使用する場合__init__.py
は、名前空間ディレクトリに no を指定します。
#2:
setup.py では、namespace_modules パラメーターを追加する必要がありますか? その場合、namespace_modules=['org.common'] または namespace_modules=['org', 'common'] を使用しますか?
名前空間パッケージの選択がネイティブ スタイルでない場合は、はいnamespace_packages
、setup()
.
#3:
どういうわけかこれを別の方法で実装するだけで、上記のすべてを忘れることができますか? おそらく、より単純な、またはより「pythonic」なものでしょうか?
Python の複雑なトピックにたどり着いたので、自分が何をしているのか、何を望んでいるのかを理解しているようで、Python Namespace パッケージを作成することがその方法であることがわかりました。これは、問題を解決するための Pythonic な方法と見なされます。
あなたの質問に加えて、ここに私が発見したいくつかのことがあります:
私はPEP420、Python Packaging guideを読み、名前空間パッケージを理解するのに多くの時間を費やしました。ここ、ここ、ここ、および SO のこのスレッドもいくつかの回答を読みました。
しかし、私の問題は、パッケージを作成した後でした。すべての手順とサンプル コードでsetuptools.setup(package=[])
関数内のパッケージが明示的にリストされているため、私のコードは失敗しました。サブパッケージ/ディレクトリが含まれていませんでした。さらに深く掘り下げると、 setuptools にはfind_namespace_package()
サブパッケージの追加にも役立つ機能があることがわかりました
編集:
へのリンクfind_namespace_packages()
(setuptools
以降のバージョン40.1.0
): https://setuptools.readthedocs.io/en/latest/setuptools.html#find-namespace-packages
編集 (2019 年 8 月 9 日):
答えを完成させるために、例を挙げて再構成しましょう。
次の解決策は、暗黙的な名前空間パッケージをサポートする Python 3.3+ を想定しています。
Python バージョン以降のソリューションを探しているので、3.5
提供されているコード サンプルを取り上げて、さらに詳しく説明しましょう。
次のように仮定します。
名前空間/Python パッケージ名:org
配布パッケージ: org_client
、org_common
パイソン:3.3+
セットアップツール:40.1.0
次のことを行うには
from org.client.client1 import mod1
from org.common import config
そして、トップレベルのディレクトリを同じに保ちます. org_client_client1_mod1
とorg_common_config
、構造を次のように変更できます
リポジトリ 1:
org_client_client1_mod1/
setup.py
org/
client/
client1/
__init__.py
submod1/
__init__.py
mod1/
__init__.py
somefile.py
file1.py
更新しましたsetup.py
from setuptools import find_namespace_packages, setup
setup(
name="org_client",
...
packages=find_namespace_packages(), # Follows similar lookup as find_packages()
...
)
リポジトリ 2:
org_common_config/
setup.py
org/
common/
__init__.py
config/
__init__.py
someotherfile.py
更新日setup.py
:
from setuptools import find_namespace_packages, setup
setup(
name="org_common",
...
packages=find_namespace_packages(), # Follows similar lookup as find_packages()
...
)
インストールするには (を使用pip
):
(venv) $ pip3 install org_common_config/
(venv) $ pip3 install org_client_client1_mod1/
更新されたピップ リストには、次のように表示されます。
(venv) $ pip3 list
...
org_client
org_common
...
ただし、それらはインポート可能ではありません。インポートするにはorg.client
、org.common
表記に従う必要があります。
理由を理解するには、ここを参照してください (venv 内を想定):
(venv) $ cd venv/lib/python3.5/site-packages/
(venv) $ ls -l | grep org
org_client
orディレクトリがないことがわかりますorg_common
。これらは名前空間パッケージとして解釈されます。
(venv) $ cd venv/lib/python3.5/site-packages/org/
(venv) $ ls -l
client/
common/
...