Pythonモジュールの絶対相対インポートと明示相対インポート


85

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

または、PEP328を使用してPython2.5で導入された、明示的な相対インポートを使用します。

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

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


「明示的な関係節」の例は構文エラーです。相対的な輸入は形式でなければなりませんfrom _ import ...ので、あなたの例は次のようになりますfrom .. import Afrom . import B
MestreLion

@MestreLion良いキャッチ、あなたは絶対に正しいです!質問をからに更新しimport ..Aましたfrom .. import A。誰かが気付くまでにたった9年しか
かから

回答:


52

絶対輸入。PEP 8から:

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

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

import A.A
import A.B.B

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

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


@Rafe、「よく書かれたプロジェクトを見てください...」何か提案はありますか?
denis 2011年

@Denis:RietveldはGuido van Rossum自身のプロジェクトなので、見るのに良い場所だと思います(code.google.com/p/rietveld)。Python標準ライブラリはそれほど優れていません。そのコードの多くは、規則に従っていません。
Rafe Kettler 2011年

68
@Rafe:Guidoによると、PEP-8のその部分は時代遅れです。mail.python.org/pipermail/python-dev/2010-October/104476.html
Brandon Rhodes

12
その声明は、現在PEP-8にはまったく含まれていません。現在、絶対インポートが推奨されていると記載されていますが、相対インポートは許容可能な代替手段です。
dano 2014

6
絶対インポートで私が抱えている問題は、別のパッケージ内でパッケージを使用する場合です。私の場合、それはgitサブモジュールとして存在します。この場合、最上位のパッケージをインポートできますが、絶対インポートで独自のモジュールを見つけることができないため、このパッケージより下のパッケージはインポートできません。一方、この最下位レベルで相対インポートを使用すると、すべて正常に機能します。
davidA 2017年

122

Pythonの相対インポートは推奨されなくなりましたが、その場合はabsolute_importを使用することを強くお勧めします。

Guido自身を引用しているこの議論を参照しください。

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

OPは、次のようなPEP328を正しくリンクします。

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

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

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

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

from __future__ import absolute_import

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

重要な注意点があるためのものである PEP 338PEP 366あなたは相対インポートを持っているか、あなたが買ってあげるfile.pyを実行することはできません- 、相対的な輸入がモジュールとしてインポートするPythonのファイルが必要ですValueError: Attempted relative import in non-package

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

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

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


9
Guidoは2010年にそれを書きました、そしてそれはまだPEPにありますか?PEPが非常に古くなっている場合、どうすれば信頼できますか?
ジャバ2014年

2
PEPは、物事を修正できるという意味で、米国の修正に似ています。拒否されたPEPSもたくさんあります。PEPは提案です。それらは受け入れられたり、拒否されたり、時代遅れになる可能性があります。これは、多くの場合、新しいPEPを意味します。PEP 8はスタイルガイドであるため、その場で変更できます。
cppLearner 2014年

2
「パッケージ内のモジュールはそれ自体を簡単にインポートできない...」という部分について混乱しています。モジュールが自分自身をインポートすることについては、これまで聞いたことがありませんでした。
matiascelasco 2014

2
考えられる1つの例@matiascelasco:foo /bar.pyとfoo / baz.pyだけでなく、別の場所にbaz.pyがある場合。バーからfoo.bazをインポートする場合は、インポートする内容を確認する必要があります。import .baz-これは、PEPで説明されている多くの同様の状況を単純化したものの1つにすぎません。
ステファノ

あなたの答えは、それらを許可する際の変更を明確に区別していません。暗黙的な相対インポートは使用しないでください。ただし、明示的な相対インポートは使用できます。暗黙の相対はPython3から削除されました。
ninMonkey 2015

33

相対インポートでは、数十の内部インポートを変更せずに後でパッケージの名前を自由に変更できるだけでなく、Pythonを返送しないため、循環インポートや名前空間パッケージなどの特定の問題を解決することに成功しました。 top」をクリックして、トップレベルの名前空間から次のモジュールの検索を最初からやり直します。


4
これは、Pythonスタイルガイドによると推奨されないスタイルです。それらは読みやすさをひどく曇らせ、あなたがほのめかす知覚された「便利さ」の価値がありません。問題を解決するために相対インポートを使用する必要がある場合、それは間違っています。
Rafe Kettler 2010年

14
他の回答に対する彼の(ブランドンローズ)コメントに注意してください。リンクは、もはや落胆していないことを示しています。
Jon Coombs 2014年

1
@RafeKettlerは、それ自体が別のパッケージに含まれているパッケージで絶対インポートをどのように使用するかを説明できますか?絶対インポートは、新しいトップレベルについて知らないため、内部パッケージ内で失敗します。相対的なインポートは引き続き機能します。そもそもパッケージを別のパッケージの中にネストするべきではないと主張する人もいるかもしれませんが、一部のコードは再利用可能であることが意図されており、これは頻繁に発生します。再利用されたコードの多くは一般向けにパッケージ化されていないため、個別のパッケージとして提供されていないため、VCSインポート/サブモジュールなどのアドホックメソッドが代わりに使用されることになります
davidA 2017年

3
@meowsqueak同意します。一部のパッケージは簡単にインストールできません(pipにない、使用したくない、python setup.py installまたはpython setup.py develop何らかの理由で)。そのような場合は、ソースコードをフォークしてgitサブモジュールとして追加します。それらのパッケージが独自のパッケージ名で絶対インポートを使用する場合、それらのインポートは失敗します。唯一の解決策は、明示的な相対インポートを使用することです。それが奨励されるべきだと私は思います。
CMCDragonkai 2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.