配置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
相关产品推荐
相关产品推荐

