設定クラスを読み込む from pydantic import BaseSettings の行で、次のエラーが出て止まることがあります。
pydantic.errors.PydanticImportError: `BaseSettings` has been moved to the `pydantic-settings` package. See https://docs.pydantic.dev/2.9/migration/#basesettings-has-moved-to-pydantic-settings for more details.
For further information visit https://errors.pydantic.dev/2.9/u/import-error
例外クラスは PydanticImportError、末尾に errors.pydantic.dev/.../u/import-error の URL が付く形で出ます。原因は、Pydantic 2 で BaseSettings が本体から pydantic-settings という別パッケージへ移されたことです。直すのは、パッケージを1つ足して import 元を1行変えるだけです。
pip install pydantic-settings
# 変更前
from pydantic import BaseSettings
# 変更後
from pydantic_settings import BaseSettings
なぜ起きるのか:BaseSettings は本体から出て別パッケージになった
BaseSettings は、環境変数や .env から設定を読み込むためのクラスです。Pydantic 1 では本体(pydantic)に入っていて、from pydantic import BaseSettings で取れました。Pydantic 2 では、この設定管理の機能が本体から切り離され、pydantic-settings という独立したパッケージへ移りました。
そのため Pydantic 2 の本体には BaseSettings という名前がありません。from pydantic import BaseSettings を書くと、Pydantic はそれが移動済みの名前だと知っていて、PydanticImportError を投げて移動先を案内します。エラー文にそのまま pydantic-settings パッケージ名と移行ガイドの URL が入っているのはそのためです。名前が消えたのではなく、取り出す場所が変わっただけなので、pydantic-settings を入れて from pydantic_settings import BaseSettings にすれば、同じクラスがそのまま使えます。
なぜ Pydantic 2 で出るのか
このエラーの引き金は Pydantic のメジャーバージョンです。Pydantic 1(例:1.10 系)では from pydantic import BaseSettings が通ります。Pydantic 2 に上げた後だけ、同じ import が PydanticImportError になります。手元の環境やこれまでの requirements.txt が Pydantic 1 のままなら踏みません。次のような場面で表面化します。
- Pydantic を 1 系から 2 系へ上げた:
pip install --upgrade pydanticや、版を固定していない環境を作り直したときに 2 系が入り、設定クラスの import だけが落ちる。 - FastAPI をきっかけに 2 系が入った:FastAPI は Pydantic 2 の上で動くので、新しく
pip install fastapiすると Pydantic 2 が一緒に入ります。ところがpip install fastapiはpydantic-settingsまでは入れません(後述)。FastAPI のチュートリアルは設定管理にBaseSettingsを使うため、その通りに書いたのに import で落ちる、という組み合わせになります。 - 手元は 1 系のまま、CI やコンテナだけ 2 系:ビルドイメージや lock ファイルの版が食い違い、片方だけ落ちる。
まず pip show pydantic pydantic-settings で、Pydantic が 2 系かどうかと、pydantic-settings が入っているかを確かめます。
FastAPI を入れても pydantic-settings は入らない
FastAPI 経由でこのエラーに当たる場合、依存の引き方に理由があります。pip install fastapi が依存として引くのは Pydantic 本体(2 系)で、エクストラを付けない素の pip install fastapi は pydantic-settings を引きません。pydantic-settings は fastapi[standard](現在の公式推奨インストール)や fastapi[all] のエクストラに入っています。つまりエクストラ無しでインストールを終えた直後の状態は、BaseSettings が本体に無い Pydantic 2 が入っていて、その移動先である pydantic-settings は入っていない、という噛み合わせになります。設定クラスを書いた瞬間に import で止まるのはこのためです。pydantic-settings は自分で明示的に入れます。
直し方1:pydantic-settings を入れて import 元を変える
自分のコードで BaseSettings を使っているなら、これが本筋です。パッケージを足して、import 元を pydantic_settings に変えます。
pip install pydantic-settings
# 変更前
from pydantic import BaseSettings
# 変更後
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
app_name: str = "errfix"
requirements.txt や pyproject.toml を使っているなら、pydantic-settings を依存に書き足します。書いておかないと、環境を作り直したときに再び入らず、同じ import エラーに戻ります。FastAPI のプロジェクトでも同様で、fastapi と並べて pydantic-settings を明示します。
Field や BaseModel など、from pydantic import ... で取っていた他の名前は本体に残っているので、そのままで動きます。移すのは BaseSettings(および pydantic-settings にまとめられた設定関連のクラス)の import 元だけです。
直し方2:まだ Pydantic 2 に移れないとき、つなぎで 1 系に留める
コード全体が Pydantic 1 の書き方(class Config での設定、.dict()、旧いバリデータなど)に依存していて、いま 2 系へ移す余裕がない場合は、当座は Pydantic を 1 系に固定して from pydantic import BaseSettings を生かす手があります。
pip install "pydantic<2"
これは 2 系への移行を先送りする暫定策です。Pydantic 1 系は保守中心の版で、新機能や新しいエコシステムの前提は 2 系に寄っていきます。requirements.txt に固定するなら、なぜ 1 系に留めているか(2 系への移行が済むまでの暫定である旨)をコメントで添えて、移行後に外せるようにしておきます。恒久的にこの版へ張り付けるのではなく、pydantic-settings を使う直し方1へ移すのが後を引きません。
FastAPI と併用しているなら、この固定の前に FastAPI の版を確認します。 FastAPI が受け付ける Pydantic の版は、FastAPI 自身の版で変わります。FastAPI 0.125 以前は Pydantic 1(1.7.4 以上)と 2 の両方を受け付けるので、その版なら pydantic<2 固定でも FastAPI は壊れません。一方 FastAPI 0.126 以降は Pydantic 2 のみ(現行の 0.139 は pydantic>=2.9)で、pydantic<2 を入れると FastAPI の依存要求と衝突するか、FastAPI 側が古い版へ引き下げられます。現行の FastAPI を使っているなら pydantic<2 は選べません——その場合は直し方1(pydantic-settings を入れて import を移す)だけが道です。この BaseSettings エラーを踏む人の多くは、すでに Pydantic 2 が入っている=新しい FastAPI 側にいるので、実際には直し方1が本筋になります。
切り分け(うまくいかないとき)
- import は直ったのに、今度は
class Configの警告やSettingsConfigDict絡みのエラーが出る:BaseSettingsを継承したクラスの中で内側のclass Configにenv_fileなどを書いていた場合、Pydantic 2 ではその書き方が非推奨です。設定はmodel_config = SettingsConfigDict(env_file=".env")の形に移します(from pydantic_settings import SettingsConfigDict)。import の移動と、この設定 API の変更は別の変更なので、順に対応します。 BaseSettings以外の名前でも似たPydanticImportErrorが出る:Pydantic 2 で本体から移動・変更された名前を 1 系の場所から読むと、同型のエラーになります。エラー文がそのまま移動先を案内するので、案内された import 元に合わせます。移行全体の対応表は Pydantic 公式の移行ガイド(エラー文中の URL)にあります。pip install fastapiは通ったのに、起動時に設定クラスで落ちる:FastAPI はpydantic-settingsを素の依存に含めません(allエクストラのみ)。pip install pydantic-settingsを追加します。pip install pydantic-settingsしたのに、まだ本体から import している箇所が残って落ちる:from pydantic import BaseSettingsをコード全体で検索し、from pydantic_settings import BaseSettingsに置き換えます。第三者ライブラリの中で古い import が残っている場合は、そのライブラリを Pydantic 2 対応版へ上げます。- 同じ「版を上げたら import が落ちた」でも、名前ごと消えている場合:Flask で
from werkzeug.urls import url_quoteが落ちる型は、移動ではなく削除で、対処は版の固定か Flask 側の更新になります(url_quote の ImportError の直し方)。Pydantic のBaseSettingsは移動先が明示されているぶん、パッケージを足せば元のコードをそのまま使えます。
検証環境
python:3.12.12-slim、ネットワーク有り- 再現:
pip install "pydantic==2.9.2"の後、from pydantic import BaseSettingsを含むスクリプトがPydanticImportError:BaseSettingshas been moved to thepydantic-settingspackageで終了コード 1 - 修正:
pip install "pydantic==2.9.2" "pydantic-settings==2.6.1"の後、from pydantic_settings import BaseSettingsに変えた同じスクリプトが終了コード 0
再現から修正までは errfix の検証ハーネスが機械的に確認しています。版境界は、pydantic==1.10.18 では from pydantic import BaseSettings が終了コード 0 で通ることを別途実測して裏づけました(Pydantic 1 では本体に BaseSettings がある)。エクストラを付けない pip install fastapi が Pydantic 2 系を引く一方で pydantic-settings を引かないこと、pydantic-settings が fastapi[standard] / fastapi[all] のエクストラに含まれること、および現行 FastAPI(0.139)が pydantic>=2.9 を要求する(Pydantic 1 を受け付けない)ことは、PyPI のパッケージメタデータ(requires_dist)とインストール後の構成で確認しています。移動の経緯や設定 API(class Config → SettingsConfigDict)の変更は、Pydantic 公式の移行ガイドに沿って書いています。エラー文言は実機出力から引用しました。