冒頭まとめ
importで次のエラーが出た場合、実行中のPythonが指定したモジュールを見つけられていません。
ModuleNotFoundError: No module named 'requests'
インストールしたつもりでも、別のPythonや仮想環境で実行していることがあります。まず、エラーが出る環境で次を確認してください。
python -c "import sys; print(sys.executable)"
python -m pip --version
python -m pip show requests
requestsは例です。実際に必要な配布パッケージの名前へ置き換えます。見つからなければ、実行するPythonを指定したうえで、そのPython経由でインストールしてください。
一方、末尾に'http' is not a packageなどが付いている場合は、手元のファイル名が本来のパッケージ名と衝突している可能性があります。再インストールより先に、何を読み込んでいるかを確認します。
エラーメッセージの意味
モジュールは、importで読み込む単位です。パッケージは、内部に別のモジュールを持てる種類のモジュールです。
ModuleNotFoundErrorはImportErrorの一種で、Python 3.6で追加されました。Pythonの例外の公式文書は、モジュールが見つからない場合と、読み込み済みモジュールを記録するsys.modulesにNoneが入っている場合に発生すると説明しています。
| 文言 | 意味 |
|---|---|
No module named 'foo' | fooを見つけられない |
No module named 'foo.bar' | foo.barを見つけられない。親の探索にも注意が必要 |
No module named 'foo.bar'; 'foo' is not a package | fooは読み込まれたが、子モジュールを持つパッケージとして扱えない |
import of foo halted; None in sys.modules | sys.modules['foo']がNoneで、読み込みが拒まれている |
これらの分岐は、CPythonのimportlib実装で確認できます。None in sys.modulesという文言だけで、別スレッドの失敗が原因だとは判断できません。
最後に表示された名前も確認してください。import requestsを実行していても、内部で必要な別モジュールを読み込めずに停止する場合があります。エラーの直前に並ぶファイル名と行番号を読むと、どの読み込みで止まったかが分かります。
最初に実行するPythonとインストール先を確認する
sys.executableは、実行中のPythonの場所を示します。python -m pip --versionでは、そのPythonで動くpipの場所を確認できます。
python -c "import sys; print(sys.executable); print(sys.prefix); print(sys.base_prefix)"
python -m pip --version
python -m pip show requests
pip showのLocationはインストール先です。別のPythonにインストールしたパッケージは、現在のPythonから読み込めるとは限りません。同じバージョンのPythonでも、仮想環境が異なれば確認が必要です。
この記事の確認では、独立した二つの仮想環境を作り、片方だけに説明用のモジュールを置きました。置いた環境では読み込めましたが、もう片方ではModuleNotFoundErrorになりました。確認に使ったPythonはCPython 3.12.14です。
エディター、ノートブック、CIでエラーが出る場合は、その実行環境の中でsys.executableを確認してください。ターミナルで成功することだけでは、別の実行環境でも読み込めるとは判断できません。
同じPythonにインストールし、仮想環境を揃える
pipの公式文書は、python -m pipが指定したPythonでpipを実行すると説明しています。単独のpipコマンドではなく、アプリケーションを動かすPythonを通して実行します。
python -m pip install requests
python -c "import requests; print(requests.__file__)"
プロジェクトにrequirements.txtがある場合は、その依存関係を使います。
python -m pip install -r requirements.txt
仮想環境は、プロジェクトごとにPythonの実行先やパッケージを分ける仕組みです。既存の.venvを使う場合の有効化は、シェルによって異なります。
| 環境 | 有効化するコマンド |
|---|---|
| Linux/macOSのbash・zsh | source .venv/bin/activate |
| Windowsのコマンドプロンプト | .venv\Scripts\activate.bat |
| WindowsのPowerShell | .\.venv\Scripts\Activate.ps1 |
有効化後も、sys.executableで実行先を確認してください。venvの公式文書によると、sys.prefix != sys.base_prefixで、実行中のPythonがvenvの仮想環境を使っているかを確認できます。
有効化せず、仮想環境のPythonを直接指定する方法もあります。Windowsのコマンドプロンプトなら、次のようにインストールと実行の両方を揃えられます。
.venv\Scripts\python.exe -m pip install requests
.venv\Scripts\python.exe app.py
DockerやCIでも、パッケージを入れた環境とアプリケーションの実行環境を揃えます。ビルド時のログにインストール成功と出ていても、実際に動く環境で同じ確認をしてください。
is not a packageならファイル名の衝突を調べる
次のエラーでは、http自体は見つかっています。ただし、http.clientを読み込めるパッケージとして扱えません。
ModuleNotFoundError: No module named 'http.client'; 'http' is not a package
手元にhttp.pyを作り、そのディレクトリでimport http.clientを実行すると、この文言を再現できました。Pythonは標準ライブラリのhttpパッケージではなく、手元のhttp.pyを読み込みます。
探索先の公式文書は、通常のスクリプト実行ではスクリプトのあるディレクトリが探索先の先頭になり、-cや-mでは現在のディレクトリが先頭になると説明しています。
python -c "import http; print(http.__file__)"
自分で作ったhttp.pyを指していれば、http_example.pyなど衝突しない名前に変更してください。実行中のプロセスが元のモジュールを保持している場合は、Pythonやノートブックの実行環境を再起動して確認します。
RequestsのIssue #7006にも、Requestsが内部でurllib3を読み込み、その先のhttp.clientで停止した報告があります。回答では、手元のhttp.pyの存在が原因候補として挙げられています。報告者による解決確認は掲載されていないため、この事例の原因を確定したものとしては扱いません。
requests.py、json.pyなども、読み込みたい名前と衝突しないようにしてください。ただし、名前衝突が必ずModuleNotFoundErrorになるわけではなく、参照の書き方によって別のエラーになります。
インストール名とimport名、自作パッケージの参照を確認する
pipに指定する名前と、Pythonで読み込む名前は一致するとは限りません。たとえばPillowは、PillowをインストールしてPILを読み込みます。
python -m pip install Pillow
python -c "from PIL import Image; print(Image.__file__)"
この違いはPyPAの公式ガイドにも明記されています。エラーの名前をそのままpipに渡すのではなく、利用するライブラリの公式文書やプロジェクトの依存関係で、必要な配布名を確認してください。
自作パッケージ内の参照も確認します。mypkgディレクトリに__init__.py、app.py、utils.pyがある構成で、app.pyから同じパッケージ内のutils.pyを読むなら、次のように書けます。
# mypkg/app.py
from . import utils
import utilsは、同じパッケージの子としてではなく、トップレベルのutilsを探します。importの公式文書は、先頭のドットを使う相対インポートを説明しています。
相対インポートを使う場合は、mypkgの親ディレクトリからモジュールとして実行します。
python -m mypkg.app
python mypkg/app.pyという直接実行では、パッケージの情報がないため、attempted relative import with no known parent packageという別のエラーになる場合があります。ファイルの配置と起動方法を揃えてください。
近いエラーとの違い
demo.pyというファイルに、存在しない名前を指定した場合の違いをCPython 3.12.14で確認しました。
| 操作・文言 | 確認する内容 |
|---|---|
import demo.childで'demo' is not a package | 親がパッケージか、同名のファイルを読み込んでいないか |
from demo import missingでImportError: cannot import name | 読み込んだモジュールからその名前を取得できるか |
import demo後のdemo.missingでAttributeError | 読み込み済みモジュールにその属性があるか |
import of demo halted; None in sys.modules | sys.modulesへの代入や、読み込みを制御する処理 |
from requests import getは、単純にrequests.getという子モジュールを探す操作ではありません。モジュールが公開する関数などの名前も取得します。そのため、from ... import ...の失敗をすべてis not a packageとして扱うことはできません。
また、読み込んだファイル内に構文の誤りがあればSyntaxErrorになります。循環した読み込みや依存先の問題もあるため、最後の一行だけでなく、そこへ至る実行履歴も確認してください。
解決手順のまとめ
最初に、エラーに出た名前とsys.executableを確認します。外部パッケージが必要なら、そのPythonでpip showを実行し、未導入なら正しい配布名でインストールしてください。
インストール済みなら、仮想環境やエディターの実行先を確認します。is not a packageが付く場合は親の__file__を調べ、自作パッケージなら参照の書き方とpython -mによる起動を見直します。
探索先を確認する必要がある場合は、次で一覧を表示できます。
python -c "import sys; print('\n'.join(sys.path))"
外部パッケージにはインストール、自作コードには配置と参照方法の確認が必要です。すべてを再インストールで直そうとせず、実行するPythonと実際の読み込み先を揃えてください。
免責事項:本記事の内容は一般的な情報提供を目的としています。設定変更は、利用しているPythonのバージョンとプロジェクトの実行環境を確認したうえで行ってください。
この記事でエラーは解決しましたか?