1. ホーム
  2. python

[解決済み] Pythonです。インポートされたパッケージからモジュールをインポートしようとすると「ModuleNotFoundError」。

2022-03-04 01:49:12

質問

macOS Mojave Version 10.14.1 で Python 3.7.1 を使用しています。

これは私のディレクトリ構造です。

man/                          
  Mans/                  
          man1.py
  MansTest/
          SoftLib/
                  Soft/
                      SoftWork/
                              manModules.py
          Unittests/
                    man1test.py

man1.py は以下を含む インポート ステートメントを使用します。 を変更したくありません。 :

from Soft.SoftWork.manModules import *

man1test.py は以下を含む インポート ステートメントを使用します。

from ...MansTest.SoftLib import Soft
from ...Mans import man1

2番目の インポート man1test.py なぜなら man1test.py の関数にアクセスする必要があります。 man1.py .

最初のインポートに対する私の根拠は、( ソフト )は、前述した インポート ステートメントを man1.py .

しかし、私の予想に反して インポート の文は man1.py を生じさせる。

ModuleNotFoundError: No module named 'Soft'

を実行すると

python3 -m man.MansTest.Unittests.man1test

上のディレクトリから man/ .

を変更せずに、このエラーを解決する方法はありますか? インポート の文は man1.py そして に何も付け加えずに sys.path ?

編集してください。 python3 -m man.ManTest.Unittests.man1test に変更しました。 python3 -m man.MansTest.Unittests.man1test

解決方法は?

はじめに にアクセスできるようにしたい場合は man1.py から man1test.py AND manModules.py から man1.py として、ファイルを適切にセットアップする必要があります。 パッケージとモジュール .

パッケージは、Pythonのモジュール名前空間を構造化する方法です。 "ドット付きモジュール名 "です。例えば、モジュール名 A.B は という名前のサブモジュール B という名前のパッケージの中で A .

...

パッケージをインポートするとき、Pythonはディレクトリを検索して sys.path パッケージのサブディレクトリを探します。

は、その __init__.py ファイルは、Pythonに ディレクトリにパッケージが含まれるようにするためです。 のような共通の名前を持つディレクトリは string 意図せず は、モジュール検索パスの後半にある有効なモジュールを隠します。

こんな感じの設定が必要です。

man
|- __init__.py
|- Mans
   |- __init__.py
   |- man1.py
|- MansTest
   |- __init.__.py
   |- SoftLib
      |- Soft
         |- __init__.py
         |- SoftWork
            |- __init__.py
            |- manModules.py
      |- Unittests
         |- __init__.py
         |- man1test.py

第2回 には、"。 ModuleNotFoundError: No module named 'Soft' によって引き起こされるエラー。 from ...Mans import man1 man1test.py を追加することです。 man1.py sys.path から の外側にあります。 MansTest パッケージを使用します。参照 モジュール検索パス をPythonのドキュメントから引用しています。しかし、もしあなたが sys.path を直接変更することもできます。 PYTHONPATH :

<ブロッククオート

sys.path はこれらの場所から初期化されます。

  • 入力スクリプトを含むディレクトリ(ファイルが指定されていない場合はカレントディレクトリ)。
  • PYTHONPATH (ディレクトリ名のリストで、シェル変数 PATH ).
  • インストールに依存したデフォルトです。

サード のために from ...MansTest.SoftLib import Soft とおっしゃっていましたが。 は、前述のman1.pyのimportステートメントを容易にするためのものでした。 "、これでインポートがうまくいくようになりましたね。もしあなたが ソフト.ソフトリブ man1.py を設定する必要があります。 man1.py を見つけるために ソフト.ソフトリブ を作成し、そこに直接インポートします。

とはいえ、どうすれば動くようになったかというと、こんな感じです。

man1.py。

from Soft.SoftWork.manModules import *
# no change to import statement but need to add Soft to PYTHONPATH

def foo():
    print("called foo in man1.py")
    print("foo call module1 from manModules: " + module1())

man1test.py

# no need for "from ...MansTest.SoftLib import Soft" to facilitate importing..
from ...Mans import man1

man1.foo()

manModules.py

def module1():
    return "module1 in manModules"

端末の出力です。

$ python3 -m man.MansTest.Unittests.man1test
Traceback (most recent call last):
  ...
    from ...Mans import man1
  File "/temp/man/Mans/man1.py", line 2, in <module>
    from Soft.SoftWork.manModules import *
ModuleNotFoundError: No module named 'Soft'

$ PYTHONPATH=$PYTHONPATH:/temp/man/MansTest/SoftLib
$ export PYTHONPATH
$ echo $PYTHONPATH
:/temp/man/MansTest/SoftLib
$ python3 -m man.MansTest.Unittests.man1test
called foo in man1.py
foo called module1 from manModules: module1 in manModules 


提案として、それらの目的を再考してみてはいかがでしょうか。 ソフトリブ ファイルです。をつなぐある種の橋渡しなのでしょうか? man1.py man1test.py ? 今のファイルの設定方法だと、期待通りに動かないような気がするんだけど。また、テスト中のコードもちょっとわかりにくいですね( man1.py ) の下にあるものをインポートしています。 MansTest ).