【Python】pytestで同じディレクトリのモジュールをimportして、”ModuleNotFoundError: No module named”を出さなくする

Code

はじまり

リサちゃん
リサちゃん

あー、”ModuleNotFoundError: No module named”だぁぁー!!

135ml
135ml

importするときによく出るやつか。

これがめんどいよな。

リサちゃん
リサちゃん

動くやつを教えて下さい・・・

135ml
135ml

はい、今回はモジュールをimportするときのコードの一例を紹介します。

今回のディレクトリ構成

今回、紹介するimport方法におけるディレクトリ構成は、以下になっています。

├── src
│   └── landmasterlibrarylocal
│       ├── file_list_getter.py
│       ├── input_controller.py
├── test
│   ├── __init__.py
│   ├── test_file_list_getter.py
│   ├── test_input_controller.py

失敗するパターン

上記のディレクトリ構成の場合に、__init__.pyfile_list_getter.pyのコードがこんな状態だったとします。__init__.pyには何も記述しません。

__init__.py

# __init.py__

file_list_getter.py

# file_list_getter.py

# Library by default
import os, sys, platform
import time
# Library by third party
import glob2
# Library by landmasterlibrary
from input_controller import repeat_input_with_multi_choices

# ・・・以下略・・・

この状態では、普通に.pyファイルを実行する分には問題ないのですが、pytestを実行すると以下のエラーが出ます。

実行

pytest

出力

====================================================================================================== ERRORS =======================================================================================================
__________________________________________________________________________________ ERROR collecting test/test_file_list_getter.py ___________________________________________________________________________________
ImportError while importing test module '/Users/landmaster/Downloads/landmasterlibrarylocal/test/test_file_list_getter.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
../../opt/anaconda3/lib/python3.9/importlib/__init__.py:127: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
test/test_file_list_getter.py:5: in <module>
    from src.landmasterlibrarylocal.file_list_getter import *
src/landmasterlibrarylocal/file_list_getter.py:10: in <module>
    from input_controller import repeat_input_with_multi_choices
E   ModuleNotFoundError: No module named 'input_controller'

成功するパターン

この"ModuleNotFoundError: No module named"が起きないようにするために、以下のように__init__.pyで記述します。

こうすることで、'../src/landmasterlibrarylocal'がモジュールの参照先に追加されます。

__init__.py

# __init.py__
import os
import sys
sys.path.append((os.path.join(os.path.dirname(__file__), '../src/landmasterlibrarylocal')))

そうすると、以下のように、”ModuleNotFoundError: No module named”が起きなくなりました。

出力

================================================================================================ test session starts ================================================================================================
platform darwin -- Python 3.9.7, pytest-7.1.1, pluggy-0.13.1
rootdir: /Users/landmaster/Downloads/landmasterlibrarylocal
plugins: freezegun-0.4.2, anyio-2.2.0, mock-3.7.0, cov-3.0.0
collected 1 item                                                                                                                                                                                                    

test/test_input_controller.py .                                                                                                                                                                               [100%]

================================================================================================= 1 passed in 1.73s =================================================================================================

おしまい

リサちゃん
リサちゃん

やったあ〜、”ModuleNotFoundError: No module named”が起きなくなったあ〜。

135ml
135ml

困った時は、解決法の一つとして検討してみてください。

以上になります!

コメント

タイトルとURLをコピーしました