できない.dev

FastAPI「Error loading ASGI app. Could not import module」の原因と直し方

Could not import module は、main.py のある場所で uvicorn を実行するか、app.main:app のように書けば直る。main:app の main はモジュール名、app は変数名だ。

公開: 更新:

要約

FastAPI のアプリを uvicorn で起動しようとすると、サーバーが立ち上がらずに次の 1 行で止まる(終了コード 3)。

ERROR:    Error loading ASGI app. Could not import module "main".

uvicorn main:app の main はファイル main.py(モジュール)、app はその中で app = FastAPI() と代入した変数を指す。公式ドキュメント(新しいタブで開く)のとおり、これは from main import app と同じ意味で、uvicorn は実行したディレクトリを起点に main を探す。main.py がそこから見えなければこのエラーになる。
上の表示は Python 3.12・FastAPI 0.143.0・uvicorn 0.54.0 で、app/main.py だけを置いたディレクトリで uvicorn main:app を実行したものだ。

解決策

1. main.py のあるディレクトリで実行する

cd backend
uvicorn main:app --reload

2. サブディレクトリならドット区切りで書く

app/main.py にあるなら、その親ディレクトリから次のように書く。app/ に __init__.py が無くても起動できた。

uvicorn app.main:app --reload

ディレクトリを移動できない事情があるなら、--app-dir(新しいタブで開く) で探す場所を足す。
指定したディレクトリが PYTHONPATH に加わる。

uvicorn --app-dir app main:app

逆に、app.main:app をさらに上のディレクトリで実行すると、No module named 'app' のトレースバックになる。
どちらの書き方でも、起点は実行したディレクトリだ。

3. : の右側を変数名に合わせる

Attribute "app" not found と出たら、main.py で FastAPI() を代入している変数の名前を確かめる。api = FastAPI() なら uvicorn main:api と書く。

4. トレースバックの最後の行を読む

Could not import module が出ずにトレースバックで終わるときは、main.py 自体は見つかっている。
最後の行の No module named '…' に出たパッケージを、uvicorn と同じ Python 環境にインストールする。

よくある原因

  1. 別のディレクトリで実行している: リポジトリのルートやホームで実行し、main.py がカレントディレクトリに無い。
  2. サブディレクトリに置いている: app/main.py のような構成で main:app と書いている。
    モジュール名は app.main になる。
  3. 変数名が違う: api = FastAPI() と書いて main:app で起動すると、メッセージが Attribute "app" not found in module "main". に変わる(終了コードは同じ 3)。
  4. 中で import しているパッケージが無い: main.py は見つかっても、その中の import sqlalchemy などが失敗すると、Could not import module ではなく ModuleNotFoundError: No module named 'sqlalchemy' のトレースバックで終わる(終了コード 1)。

この手順で直った?