You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

配置Pydantic BaseSettings时遇Forward reference语法错误求助

解决SyntaxError: Forward reference must be an expression错误

问题重现

报错信息:

Forward reference must be an expression -- got 'postgresql

完整报错日志:

Traceback (most recent call last):

  File "/usr/local/lib/python3.9/typing.py", line 528, in __init__

    code = compile(arg, '<string>', 'eval')

  File "<string>", line 1

    postgresql+asyncpg://postgres:postgres@db:5432/blog

                      ^

SyntaxError: invalid syntax


During handling of the above exception, another exception occurred:


Traceback (most recent call last):

  File "/code/asgi.py", line 3, in <module>

    from api.app import create_app

  File "/code/api/app.py", line 2, in <module>

    from api.database import create_db_and_tables

  File "/code/api/database.py", line 3, in <module>

    from api.config import settings

  File "/code/api/config.py", line 8, in <module>

    class Settings(BaseSettings):

  File "/usr/local/lib/python3.9/site-packages/pydantic/main.py", line 179, in __new__

    annotations = resolve_annotations(namespace.get('__annotations__', {}), namespace.get('__module__', None))

  File "/usr/local/lib/python3.9/site-packages/pydantic/typing.py", line 395, in resolve_annotations

    value = ForwardRef(value, is_argument=False, is_class=True)

  File "/usr/local/lib/python3.9/typing.py", line 530, in __init__

    raise SyntaxError(f"Forward reference must be an expression -- got {arg!r}")

SyntaxError: Forward reference must be an expression -- got 'postgresql+asyncpg://postgres:postgres@db:5432/blog'

出错的Settings类代码:

class Settings(BaseSettings):
    PROJECT_NAME: str = f"SQLModel API - {os.getenv('ENV', 'development').capitalize()}"
    DESCRIPTION: str = "A FastAPI + SQLModel production-ready API"
    ENV: str = os.getenv('ENV', 'development')
    VERSION: str = "1"
    SECRET_KEY: str = secrets.token_urlsafe(32)
    # DATABASE_URI: Optional[PostgresDsn] = None
    DATABASE_URI: os.environ.get("DATABASE_URL")  # sql

Docker Compose环境变量配置:

services:
  web:
    build:
      context: .
      dockerfile: "Dockerfile"
    command: python asgi.py
    volumes:
      - .:/code
    ports:
      - 8004:8000
    environment:
      - DATABASE_URL=postgresql+asyncpg://postgres:postgres@db:5432/blog
    depends_on:

报错原因

你错误地将os.environ.get("DATABASE_URL")的返回值(即环境变量中的数据库连接字符串)写在了类型注解的位置(冒号后面),而不是作为属性的默认值放在等号后。

Pydantic的BaseSettings类要求类属性遵循属性名: 类型 = 默认值的格式。当你写成DATABASE_URI: os.environ.get("DATABASE_URL")时,Python会尝试把环境变量返回的字符串postgresql+asyncpg://postgres:postgres@db:5432/blog当作类型来解析,这个字符串包含+、://等不符合Python语法的符号,因此触发了语法错误。

解决方案

修正Settings类中DATABASE_URI的写法,明确指定类型,并将环境变量读取逻辑放在默认值位置:

方法1:使用str类型(简单直接)

import os
import secrets
from pydantic import BaseSettings

class Settings(BaseSettings):
    PROJECT_NAME: str = f"SQLModel API - {os.getenv('ENV', 'development').capitalize()}"
    DESCRIPTION: str = "A FastAPI + SQLModel production-ready API"
    ENV: str = os.getenv('ENV', 'development')
    VERSION: str = "1"
    SECRET_KEY: str = secrets.token_urlsafe(32)
    # 正确写法:先指定类型str,再设置默认值
    DATABASE_URI: str = os.environ.get("DATABASE_URL")

方法2:使用PostgresDsn类型(更严谨,自动校验格式)

如果你需要自动校验数据库连接字符串的格式,可以使用Pydantic提供的PostgresDsn类型:

import os
import secrets
from pydantic import BaseSettings, PostgresDsn

class Settings(BaseSettings):
    PROJECT_NAME: str = f"SQLModel API - {os.getenv('ENV', 'development').capitalize()}"
    DESCRIPTION: str = "A FastAPI + SQLModel production-ready API"
    ENV: str = os.getenv('ENV', 'development')
    VERSION: str = "1"
    SECRET_KEY: str = secrets.token_urlsafe(32)
    # 使用PostgresDsn类型并设置默认值
    DATABASE_URI: PostgresDsn = os.environ.get("DATABASE_URL")

方法3:利用BaseSettings自动读取环境变量

BaseSettings会自动读取与属性名同名的环境变量(大小写不敏感),因此你可以简化写法,无需手动调用os.environ.get:

import secrets
from pydantic import BaseSettings, PostgresDsn

class Settings(BaseSettings):
    PROJECT_NAME: str = f"SQLModel API - {os.getenv('ENV', 'development').capitalize()}"
    DESCRIPTION: str = "A FastAPI + SQLModel production-ready API"
    ENV: str = "development"
    VERSION: str = "1"
    SECRET_KEY: str = secrets.token_urlsafe(32)
    # 自动读取环境变量DATABASE_URL
    DATABASE_URI: PostgresDsn

这样修改后,代码就能正确解析环境变量中的数据库连接字符串,不会再触发语法错误。

内容的提问来源于stack exchange,提问作者Alwaysblue

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 06:25:22