web-dev-qa-db-ja.com

Python 3が機能しない場合の相対インポート

次のディレクトリがあります。

mydirectory
├── __init__.py
├── file1.py 
└── file2.py

File1.pyで関数fが定義されています。

File2.pyで、私が

from .file1 import f

次のエラーが表示されます。

SystemError:親モジュール ''がロードされていません。相対インポートを実行できません

どうして?そして、それを機能させる方法は?

51

file1およびfile2は同じディレクトリにあります。__init__.pyファイル。スケールアップする場合は、そのままにしておきます。

同じディレクトリ内のファイルに何かをインポートするには、次のようにします

from file1 import f

つまり、相対パスを実行する必要はありません.file1は同じディレクトリにあるためです。

アプリケーション全体を実行するメイン関数、スクリプトなどが別のディレクトリにある場合は、実行される場所に関連するすべてのものを作成する必要があります。

24
mrKelley

パッケージ内のモジュールを実行可能ファイルとして起動することは、悪い習慣です

何かを開発するときは、他のプログラムによってインポートされることを意図したライブラリを構築するため、そのサブモジュールを直接実行することはあまり意味がありません。または、実行可能ファイルを構築します。パッケージの。

これが、setup.pyでパッケージとスクリプトを区別する理由です。パッケージはsite-packagesの下に置かれ、スクリプトは/usr/bin(またはOSに応じて同様の場所)の下にインストールされます。

したがって、次のレイアウトを使用することをお勧めします。

/
├── mydirectory
|    ├── __init__.py
|    ├── file1.py 
└── file2.py

file2.pyは、ライブラリを使用する他のコードとしてfile1.pyをインポートしますmydirectoryabsolute import

from mydirectory.file1 import f

プロジェクトのsetup.pyスクリプトを記述する場合、mydirectoryをパッケージとして、file2.pyをスクリプトとしてリストするだけで、すべてが機能します。 sys.pathをいじる必要はありません。

何らかの理由で実際にパッケージのサブモジュールを実際に実行したい場合は、-mスイッチを使用するのが適切な方法です。

python -m mydirectory.file1

これにより、パッケージ全体がロードされ、モジュールがスクリプトとして実行され、相対インポートが成功します。

個人的にはこれを避けたいです。また、多くの人があなたがこれを行うことができることさえ知らず、あなたと同じエラーを受け取り、パッケージが壊れていると思うようになるためです。


現在受け入れられている回答については、implicit相対インポートfrom file1 import fを使用するだけで、同じディレクトリにあるため機能するためです。

これはwrong

  • 暗黙の相対インポートが許可されていないpython3ではnot動作せず、file1モジュールをインストールした場合は確実に壊れます(あなたの代わりにインポートされるためモジュール!)。
  • 動作しても、file1mydirectoryパッケージの一部としては表示されません。これはcan問題です。

    たとえば、file1pickleを使用する場合、データの適切なロード/アンロードにはパッケージの名前が重要です。

42
Bakuriu

pythonソースファイルを起動する場合、相対インポートを使用して現在のパッケージにある別のファイルをインポートすることは禁止されています。

ドキュメント では、次のように言われています:

相対的なインポートは、現在のモジュールの名前に基づいていることに注意してください。メインモジュールの名前は常に「__main__」であるため、Pythonアプリケーションのメインモジュールとして使用するためのモジュールは、常に絶対インポートを使用する必要があります。

@ mrKelley が言ったように、そのような状況では絶対インポートを使用する必要があります。

20
stalk
myproject/

mypackage
├── __init__.py
├── file1.py
├── file2.py 
└── file3.py

mymainscript.py

あるファイルから別のファイルにインポートする例

#file1.py
from myproject import file2
from myproject.file3 import MyClass

パッケージ例をメインスクリプトにインポートします

#mymainscript.py
import mypackage

https://docs.python.org/3/tutorial/modules.html#packages

https://docs.python.org/3/reference/import.html#regular-packages

https://docs.python.org/3/reference/simple_stmts.html#the-import-statement

https://docs.python.org/3/glossary.html#term-import-path

変数sys.pathは、モジュールのインタープリターの検索パスを決定する文字列のリストです。これは、環境変数PYTHONPATHから取得したデフォルトパス、またはPYTHONPATHが設定されていない場合は組み込みのデフォルトから初期化されます。標準のリスト操作を使用して変更できます。

import sys
sys.path.append('/ufs/guido/lib/python')
sys.path.insert(0, '/ufs/guido/myhaxxlib/python')

最初に挿入すると、名前の競合が発生した場合に、パスが他のパス(組み込みパスを含む)よりも先に検索されるようになります。

0
The Demz