相対インポート-ModuleNotFoundError:xという名前のモジュールはありません


179

私が本当に座ってpython 3を試したのはこれが初めてで、惨めに失敗しているようです。次の2つのファイルがあります。

  1. test.py
  2. config.py

config.pyには、いくつかの関数といくつかの変数が定義されています。私はそれを次のように取り除きました:

config.py

debug = True

test.py

import config
print (config.debug)

私も持っています __init__.py

ただし、次のエラーが発生します。

ModuleNotFoundError: No module named 'config'

私はpy3規則が絶対インポートを使用することであることを認識しています:

from . import config

ただし、これにより次のエラーが発生します。

ImportError: cannot import name 'config'

だから私はここで何をすべきかについて途方に暮れています...どんな助けでも大歓迎です。:)


エラーを再現できません。このコードをどのように実行しますか?
コッパーフィールド2017

2
私はそれをpythonに付属しているアイドル状態で実行しpython test.pyます。私はpyCharmを持っていませんが、おそらく問題を引き起こしているpyCharmのいくつかの悪い構成です
Copperfield

1
非常に奇妙な。私はWinPythonを使用しています-python.orgからバニラPython 3.6をダウンロードするだけで問題なく動作します。通訳をチェックしようと思ったことはありません!ありがとう!
ブリッツマン2017

1
私の推測では、PYTHONPATHでファンキーなことが起こっています。IDE設定またはシステム環境変数、あるいはその両方を確認してください。
マーティンTournoij

1
これとまったく同じ問題があります。pycharmではありません!python3です。python2でも動作しますが、python3を使用すると、このエラーが表示されます。とてもイライラします。

回答:


164

TL; DR:モジュールはパッケージの一部ではないため実行するファイルからの相対インポートはできません__main__

絶対インポート -で利用可能なインポートsys.path

相対インポート -現在のモジュールに関連するものをインポートします。パッケージの一部である必要があります

両方のバリアントをまったく同じ方法で実行している場合、どちらかが機能するはずです。とにかく、ここに何が起こっているのかを理解するのに役立つ例があります。次のmain.pyような全体的なディレクトリ構造を持つ別のファイルを追加しましょう:

.
./main.py
./ryan/__init__.py
./ryan/config.py
./ryan/test.py

そしてtest.pyを更新して何が起こっているのか見てみましょう:

# config.py
debug = True


# test.py
print(__name__)

try:
    # Trying to find module in the parent package
    from . import config
    print(config.debug)
    del config
except ImportError:
    print('Relative import failed')

try:
    # Trying to find module on sys.path
    import config
    print(config.debug)
except ModuleNotFoundError:
    print('Absolute import failed')
# main.py
import ryan.test

まずtest.pyを実行しましょう:

$ python ryan/test.py
__main__
Relative import failed
True

ここでは「テストは」である__main__モジュール、パッケージに属するについて何も知りません。ただしimport configryanフォルダーはsys.pathに追加されるため、機能するはずです。

代わりにmain.pyを実行してみましょう:

$ python main.py
ryan.test
True
Absolute import failed

そして、ここでのテストは「ryan」パッケージの内部にあり、相対的なインポートを実行できます。import configPython 3では暗黙的な相対インポートが許可されていないため、失敗します。

これがお役に立てば幸いです。

PS:Python 3を使用している場合は、__init__.pyファイルは必要ありません。


3
絶対インポートを常に機能させるためにできることはありますか?のように、sys.path.append('/some/path/my_module')内部で呼び出し/some/path/my_module/__init__.pyますか?
James T.

4
@JamesT。はい、sys.path実行時に変更することはかなり一般的です(github.com/…)。PYTHONPATH環境変数を設定することもできます。
Igonato 2017

6
「Python 3を使用している場合は、__init__.pyファイルはもう必要ありません。」面白い。これについて詳しく説明できますか?私は、パッケージ解決メカニズムは、2と3の間にすべてのことはあまり変わっていないという印象の下にあった
ケビン・

2
「Python 3を使用している場合は、__init__.pyファイルは必要ありません。」逆に、パッケージが2と3の両方で機能するようにしたい場合はどうですか?そして、はなはだ-古く2009参照は何__init__.pyのために?そして最も高く支持されている答えは「パッケージの一部です」です。「通常のパッケージ[古い、3.3より前]」「名前空間パッケージ[3.3+]」の違いを随所に、そして頻繁に強調する必要があります
smci

61

私はそれを考え出した。特にpython2から来る、非常にイライラします。

.相対か絶対かに関係なく、モジュールにaを追加する必要があります。

以下のようにディレクトリ設定を作成しました。

/main.py
--/lib
  --/__init__.py
  --/mody.py
  --/modx.py

modx.py

def does_something():
    return "I gave you this string."

mody.py

from modx import does_something

def loaded():
    string = does_something()
    print(string)

main.py

from lib import mody

mody.loaded()

mainを実行すると、これが起こります

$ python main.py
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    from lib import mody
  File "/mnt/c/Users/Austin/Dropbox/Source/Python/virtualenviron/mock/package/lib/mody.py", line 1, in <module>
    from modx import does_something
ImportError: No module named 'modx'

私は2to3を実行し、コア出力はこれでした

RefactoringTool: Refactored lib/mody.py
--- lib/mody.py (original)
+++ lib/mody.py (refactored)
@@ -1,4 +1,4 @@
-from modx import does_something
+from .modx import does_something

 def loaded():
     string = does_something()
RefactoringTool: Files that need to be modified:
RefactoringTool: lib/modx.py
RefactoringTool: lib/mody.py

mody.pyのimportステートメントを修正して修正する必要がありました

try:
    from modx import does_something
except ImportError:
    from .modx import does_something


def loaded():
    string = does_something()
    print(string)

次に、main.pyを再度実行して、期待される出力を取得しました

$ python main.py
I gave you this string.

最後に、クリーンアップして2と3の間で移植できるようにします。

from __future__ import absolute_import
from .modx import does_something

1
ことは注目に値するtry/exceptのロード手順は(一部の人々が使用する必要がありますよう、ここで働く本当の成分であるtry:scripts.modxexcept: modx)、そして私のために、この問題を解決したものでした。
Justapigeon

40

PYTHONPATHの設定もこの問題の解決に役立ちます。

これは、Windowsでそれを行う方法です

set PYTHONPATH=.


11
PYTHONPATHをメインコードディレクトリに設定すると、問題が解決しました!
オタク

1
Linuxでも動作します。PYTHONPATH =をエクスポートします。
rjdkolb

29

モジュールのパスをに追加する必要がありますPYTHONPATH


UNIXの場合(Linux、OSXなど)

export PYTHONPATH="${PYTHONPATH}:/path/to/your/module/"

Windowsの場合

set PYTHONPATH=%PYTHONPATH%;C:\path\to\your\module\

4
@Giorgosに感謝します!これは、Dockerイメージにルートディレクトリを設定しようとしている場合に特に当てはまります。
トニーフレイザー

15

あなたの例を試しました

from . import config

以下はSystemErrorを得た:
/usr/bin/python3.4 test.py
トレースバック(最新の呼び出しの最後):
ファイル「test.py」、行1、内
からを。インポート構成
SystemError:親モジュール ''がロードされていないため、相対インポートを実行できません


これは私にとってはうまくいきます:

import config
print('debug=%s'%config.debug)

>>>debug=True

Python:3.4.2でテスト済み-PyCharm 2016.3.2


このPyCharmの横に、この名前インポートすることができます。
クリックするconfigヘルプアイコンが表示されます。 ここに画像の説明を入力してください


11

次のファイルをテストディレクトリに追加するだけで、Pythonがテストの前に実行します。

__init__.py file

import os
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

これはまさに私が探していたものです。この答えを共有してくれてありがとう!!!
Mayur '10

このようなことを行うと、リンター(pylint3)エラーが発生します。エラーはこれに似ています。filename.py:12:0:C0413:インポート "import abc.def.ghi.file_util as file_util"はモジュールの先頭に配置する必要があります(間違ったインポート位置)
Sharad

6

PYTHONPATHルートプロジェクトディレクトリに環境変数を設定します。

UNIXライクを考慮:

export PYTHONPATH=.

4

この例はPython 3.6で動作します。

Run -> Edit ConfigurationsPyCharmに移動し、そこでエントリを削除して、PyCharmを介してコードを再度実行することをお勧めします。

それが機能しない場合は、プロジェクトインタープリター([設定]-> [プロジェクトインタープリター])を確認し、構成のデフォルトを実行します([実行]-> [構成の編集...])。


4

モジュールを呼び出す前に、正しいsys.pathリストを宣言します。

import os, sys

#'/home/user/example/parent/child'
current_path = os.path.abspath('.')

#'/home/user/example/parent'
parent_path = os.path.dirname(current_path)

sys.path.append(parent_path)
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'child.settings')

1

元の投稿へのコメントで述べられているように、これは私が何らかの理由で使用していたpythonインタープリターの問題であり、pythonスクリプトに問題はないようです。WinPythonバンドルからpython.orgの公式python 3.6に切り替えたところ、問題なく動作しました。助けてくれてありがとう:)


1
うーん、これを言うのは嫌いですが、同じことが私に起こりました。環境を再作成すると、問題が修正されます。私の場合、テストを実行するとこのエラーが発生しました。同じ環境で、同じモジュールをインポートしようとしても機能しました。それらをすべて修正した環境の再作成(同じPythonバージョン3.6)
naoko

1
プロジェクトソースファイル(ビュー、モジュール、テンプレートなど)に対して特別にパスを処理する方法はIDEによって異なります。プロジェクトが適切に構造化およびコーディングされている場合、すべての(標準)IDEで機能するはずです。WinPythonのような一般的なIDEに問題があるということは、問題が実際にプロジェクトに起因していることを意味します。上記のように、問題はuser3159377による「モジュールに。を追加する必要があります」であり、これが受け入れられる答えです。
winux

1

Python 3以降を使用している場合は、以下の行を追加してみてください

import os, sys
dir_path = os.path.dirname(os.path.realpath(__file__))
parent_dir_path = os.path.abspath(os.path.join(dir_path, os.pardir))
sys.path.insert(0, parent_dir_path)

0

試す

from . import config

これは、同じフォルダレベルからインポートすることです。直接インポートしようとすると、従属であると想定されます

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.