次のディレクトリがあります。
mydirectory
├── __init__.py
├── file1.py
└── file2.py
File1.pyで関数fが定義されています。
File2.pyで、私が
from .file1 import f
次のエラーが表示されます。
SystemError:親モジュール ''がロードされていません。相対インポートを実行できません
どうして?そして、それを機能させる方法は?
file1
およびfile2
は同じディレクトリにあります。__init__.py
ファイル。スケールアップする場合は、そのままにしておきます。
同じディレクトリ内のファイルに何かをインポートするには、次のようにします
from file1 import f
つまり、相対パスを実行する必要はありません.file1
は同じディレクトリにあるためです。
アプリケーション全体を実行するメイン関数、スクリプトなどが別のディレクトリにある場合は、実行される場所に関連するすべてのものを作成する必要があります。
パッケージ内のモジュールを実行可能ファイルとして起動することは、悪い習慣です。
何かを開発するときは、他のプログラムによってインポートされることを意図したライブラリを構築するため、そのサブモジュールを直接実行することはあまり意味がありません。または、実行可能ファイルを構築します。パッケージの。
これが、setup.py
でパッケージとスクリプトを区別する理由です。パッケージはsite-packages
の下に置かれ、スクリプトは/usr/bin
(またはOSに応じて同様の場所)の下にインストールされます。
したがって、次のレイアウトを使用することをお勧めします。
/
├── mydirectory
| ├── __init__.py
| ├── file1.py
└── file2.py
file2.py
は、ライブラリを使用する他のコードとしてfile1.py
をインポートしますmydirectory
、absolute import:
from mydirectory.file1 import f
プロジェクトのsetup.py
スクリプトを記述する場合、mydirectory
をパッケージとして、file2.py
をスクリプトとしてリストするだけで、すべてが機能します。 sys.path
をいじる必要はありません。
何らかの理由で実際にパッケージのサブモジュールを実際に実行したい場合は、-m
スイッチを使用するのが適切な方法です。
python -m mydirectory.file1
これにより、パッケージ全体がロードされ、モジュールがスクリプトとして実行され、相対インポートが成功します。
個人的にはこれを避けたいです。また、多くの人があなたがこれを行うことができることさえ知らず、あなたと同じエラーを受け取り、パッケージが壊れていると思うようになるためです。
現在受け入れられている回答については、implicit相対インポートfrom file1 import f
を使用するだけで、同じディレクトリにあるため機能するためです。
これはwrong!
file1
モジュールをインストールした場合は確実に壊れます(あなたの代わりにインポートされるためモジュール!)。動作しても、file1
はmydirectory
パッケージの一部としては表示されません。これはcan問題です。
たとえば、file1
がpickle
を使用する場合、データの適切なロード/アンロードにはパッケージの名前が重要です。
pythonソースファイルを起動する場合、相対インポートを使用して現在のパッケージにある別のファイルをインポートすることは禁止されています。
ドキュメント では、次のように言われています:
相対的なインポートは、現在のモジュールの名前に基づいていることに注意してください。メインモジュールの名前は常に「__main__」であるため、Pythonアプリケーションのメインモジュールとして使用するためのモジュールは、常に絶対インポートを使用する必要があります。
@ mrKelley が言ったように、そのような状況では絶対インポートを使用する必要があります。
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')
最初に挿入すると、名前の競合が発生した場合に、パスが他のパス(組み込みパスを含む)よりも先に検索されるようになります。