現在、Python3で動作し、絶対インポートを使用して1つのモジュールを別のモジュールにインポートしようとしていますが、エラーModuleNotFoundError: No module named '__main__.moduleB'; '__main__' is not a package
が表示されます。このプロジェクト構造を考えてみましょう
proj
__init__.py3 (empty)
moduleA.py3
moduleB.py3
moduleA.py3
from .moduleB import ModuleB
ModuleB.hello()
moduleB.py3
class ModuleB:
def hello():
print("hello world")
その後、python3 moduleA.py3
を実行するとエラーが発生します。ここで何を変更する必要がありますか?
.moduleB
は相対的なインポートです。相対は、親モジュールが最初にインポートまたはロードされたときにのみ機能します。つまり、現在のランタイム環境のどこかにproj
をインポートする必要があります。コマンドpython3 moduleA.py3
を使用している場合、親モジュールをインポートする機会はありません。あなたはできる:
from proj.moduleB import moduleB
またはrun.py
を呼び出す別のスクリプト、たとえばfrom proj import moduleA
を作成できますPythonの素晴らしい土地への旅に幸運を。
Md-sabuj-sarkerの答えに加えて、 Pythonモジュールのドキュメント には本当に良い例があります。
これは、ドキュメントが intra-package-references について述べていることです:
相対的なインポートは、現在のモジュールの名前に基づいていることに注意してください。メインモジュールの名前は常に
"__main__"
であるため、Pythonアプリケーションのメインモジュールとして使用するモジュールは常に絶対インポートを使用する必要があります。
python3 moduleA.py3
を実行する場合、moduleA
がメインモジュールとして使用されるため、絶対インポートの使用は正しいことのように見えます。
ただし、何らかの理由でパッケージにパッケージと同じ名前のモジュールファイルが含まれている場合(少なくとも、Python 3.7では)、この絶対インポート(from package.module import something
)が失敗することに注意してください。したがって、たとえば、次のような場合は失敗します(OPの例を使用):
proj/
__init__.py (empty)
proj.py (same name as package)
moduleA.py
moduleB.py
その場合、次のようになります。
ModuleNotFoundError: No module named 'proj.moduleB'; 'proj' is not a package
または、提案されているように、.
のfrom .moduleB import
を削除することができます here および here 、これは私のPyCharm(2018.2.4 )これを「未解決の参照」としてマークし、オートコンプリートに失敗します。
私は、実際にpipでインストールできるPythonパッケージであるプロジェクトを開発していますが、コマンドも公開していますラインインターフェイス。 pip install .
を使用してプロジェクトをインストールした後、プロジェクトの実行に問題はありませんが、プロジェクトファイルのいずれかを変更した後に毎回これを行うのは誰ですか?単純なpython mypackage/main.py
で全体を実行する必要がありました。
/my-project
- README.md
- setup.py
/mypackage
- __init__.py
- main.py
- common.py
main.py
モジュールからcommon.py
のいくつかの関数をインポートしようとしました。さまざまなエラーが発生するさまざまな構成を試しましたが、観察結果を共有し、今後のメモも残しておきたいと思います。
私が最初に試したのは相対的なインポートでした:
from .common import my_func
python mypackage/main.py
という単純なアプリケーションを実行しました。残念ながら、これにより次のエラーが発生しました。
ModuleNotFoundError: No module named '__main__.common'; '__main__' is not a package
この問題の原因は、main.py
がpython
コマンドによって直接実行されたため、__main__
という名前のメインモジュールになったことです。この情報を、使用した相対インポートに関連付けた場合、エラーメッセージ__main__.common
にある内容を取得します。これは Pythonドキュメント で説明されています:
相対的なインポートは、現在のモジュールの名前に基づいていることに注意してください。メインモジュールの名前は常に
__main__
であるため、Pythonアプリケーションのメインモジュールとして使用するモジュールは常に絶対インポートを使用する必要があります。
pip install .
を使用してパッケージをインストールして実行すると、完全に正常に機能しました。 Pythonコンソールにmypackage.main
モジュールをインポートすることもできました。そのため、直接実行するだけでは問題があるようです。
ドキュメントのアドバイスに従って、インポートステートメントを別のものに変更しましょう。
from common import my_func
これを以前のように実行しようとすると:python mypackage/main.py
、それは期待通りに動作します!ただし、私のように、pipを使用してインストールした後、スタンドアロンのコマンドラインツールとして動作する必要があるものを開発する場合は注意が必要です。 pip install .
でパッケージをインストールし、実行しようとしました...
ModuleNotFoundError: No module named 'common'
さらに悪いことに、Pythonコンソールを開いてmain
モジュールを手動でインポートしようとすると(import mypackage.main
)、上記と同じエラーが発生しました。その理由は簡単です:common
はもはや相対的なインポートではないので、Pythonはインストールされたパッケージでそれを見つけようとします。そのようなパッケージはありません。それが失敗する理由です。
絶対インポートを使用したソリューションは、python
コマンドで実行される典型的なPythonアプリを作成する場合にのみうまく機能します。
common
モジュールをインポートする3番目の可能性もあります。
from mypackage.common import my_func
これは、mypackage
のコンテキストから行う限り、relative importアプローチとあまり変わりません。繰り返しますが、python mypackage/main.py
でこれを実行しようとすると、同様の結果になります。
ModuleNotFoundError: No module named 'mypackage'
どんなにいらいらするかもしれません、通訳は正しいです、あなたはそのようなパッケージをインストールしていません。
絶対インポート(ドットなし)を使用するだけで、すべて問題ありません。
アプリのインストール時にこのように必要になるため、相対インポート、または先頭にパッケージ名を使用したインポートを使用します。開発でそのようなモジュールを実行する場合、Pythonは-m
オプションで実行できます:
-m mod : run library module as a script (terminates option list)
python mypackage/main.py
の代わりに、python -m mypackage.main
のようにします。
モジュールをインポートする前にこれを行うことができます:
moduleA.py3
import os
import re
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from moduleB import ModuleB
ModuleB.hello()
現在のディレクトリを環境ディレクトリに追加します