99

Python アプリケーションでパッケージをインポートするための推奨される方法について疑問に思っています。次のようなパッケージ構造があります。

project.app1.models
project.app1.views
project.app2.models

project.app1.viewsインポートproject.app1.modelsproject.app2.models. これを行うには 2 つの方法があります。

絶対インポートの場合:

import A.A
import A.B.B

またはPEP 328 を使用して Python 2.5 で導入されたように、明示的な相対インポートを使用します。

# explicit relative
from .. import A
from . import B

これを行うための最もpythonicな方法は何ですか?

4

3 に答える 3

137

Python の相対インポートはもはや強く推奨されていませんが、その場合は absolute_import を使用することを強くお勧めします。

Guido自身を引用しているこの議論を見てください:

「これはほとんど歴史的なことではありませんか?新しい相対インポート構文が実装されるまで、相対インポートにはさまざまな問題がありました.短期的な解決策は、それらを使用しないことを推奨することでした.長期的な解決策は、明確な構文を実装することでした.今反勧告を撤回する時が来ました. もちろん、船外に出ることはありません.

OPは、次のように言うPEP 328を正しくリンクしています:

いくつかのユースケースが提示されましたが、その中で最も重要なものは、サブパッケージを編集することなく大きなパッケージの構造を再配置できることです。さらに、パッケージ内のモジュールは、相対インポートなしでは簡単にインポートできません。

ほぼ重複する質問も参照してくださいPythonで相対インポートを使用する場合または理由

もちろん、それはまだ好みの問題として残っています。相対インポートを使用してコードを移動する方が簡単ですが、予期せず問題が発生する可能性もあります。インポートの名前を変更することはそれほど難しくありません。

PEP 328 からの新しい動作を強制するには、次を使用します。

from __future__ import absolute_import

この場合、暗黙的な相対インポートはできなくなります (例:import localfileのみ動作しなくなりますfrom . import localfile)。クリーンで将来性のある動作のためには、absolute_import を使用することをお勧めします。

重要な警告は、 PEP 338およびPEP 366のため、相対インポートでは python ファイルをモジュールとしてインポートする必要があることです。相対インポートを持つ file.py を実行することはできませんValueError: Attempted relative import in non-package

最適なアプローチを評価する際には、この制限を考慮する必要があります。Guido は、どのような場合でも、モジュールからスクリプトを実行することに反対しています。

私は、これと __main__ 機構の他の提案されたいじりについて -1 です。唯一の使用例は、たまたまモジュールのディレクトリ内に存在するスクリプトを実行しているようです。これは、私が常にアンチパターンとして見てきたものです。私の考えを変えさせるには、そうではないことを私に納得させなければなりません。

この問題に関する徹底的な議論は SO で見つけることができます。再。Python 3 これは非常に包括的です:

于 2013-05-25T09:54:02.490 に答える
63

絶対輸入。PEP 8 から:

パッケージ内インポートの相対インポートはお勧めできません。すべてのインポートには、必ず絶対パッケージ パスを使用してください。PEP 328 [7] が Python 2.5 で完全に実装された今でも、明示的な相対インポートのスタイルは積極的に推奨されていません。絶対インポートは移植性が高く、通常は読みやすいです。

明示的な相対インポートは優れた言語機能ですが (私は推測します)、絶対インポートほど明示的ではありません。より読みやすい形式は次のとおりです。

import A.A
import A.B.B

特に複数の異なる名前空間をインポートする場合。パッケージ内からのインポートを含むよく書かれたプロジェクト/チュートリアルを見ると、通常はこのスタイルに従っています。

より明確にするために行ういくつかの余分なキーストロークは、将来、他の人 (そしておそらくあなた) があなたの名前空間を理解しようとするときに多くの時間を節約します (特に、3.x に移行した場合、パッケージの一部が名称が変更されています)。

于 2010-11-17T22:22:48.073 に答える
41

相対インポートは、何十もの内部インポートを変更することなく、後でパッケージの名前を自由に変更できるようにするだけでなく、循環インポートや名前空間パッケージなどに関連する特定の問題の解決にも成功しました。 top" を使用して、最上位の名前空間から次のモジュールの検索を最初からやり直します。

于 2010-11-17T22:25:57.380 に答える