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