1、入口参数必须经 Pydantic 校验

翻译:controller层的入参必须通过继承Pydantic的BaseModel进行格式校验。校验时如果格式不一样先强制转换,转换成功也算正确。

from datetime import datetime
from pydantic import BaseModel
# 1. 定义数据模型
class User(BaseModel):
    id: int
    name: str = "John Doe"  # 有默认值,可选
    signup_ts: datetime | None = None  # 允许为None,但如果是字符串会转成datetime
# 2. 外部来的数据,类型有些"不标准"
external_data = {
    'id': '123',  # 这是个字符串!
    'signup_ts': '2026-07-29 12:00',  # 这也是个字符串!
}
# 3. Pydantic自动校验和转换
user = User(**external_data)
print(user.id)          # 输出: 123 (已经是int了)
print(user.signup_ts)   # 输出: 2026-07-29 12:00:00 (已变成datetime对象)

如果需要抛出异常使用对应方法

from pydantic import BaseModel, ValidationError
class User(BaseModel):
    id: int
    name: str
# 故意传入错误数据
try:
    user = User(id="abc", name="Alice")  # "abc" 无法转成 int
except ValidationError as e:
    print(e)

如果使用了FastAPI框架,则自动处理异常

from fastapi import FastAPI
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):  # FastAPI 会基于 'Item' 这个注解来校验请求体
    return item

2、可选字段标注 Optional[T]T | None

翻译:可以为空的参数,代码里写明可以为空

# ❌ 不标 Optional → 必填
class CreateTaskRequest(BaseModel):
    task_type: str          # 必填,不传 → 422 报错
# ✅ 标 Optional → 可选
class CreateTaskRequest(BaseModel):
    task_type: str                    # 必填
    timeout: int | None = None        # 可选,不传就是 None
    remark: Optional[str] = None      # 同上,老写法

3、公开函数必须有类型注解

翻译:公开可以调用的方法必须写上返回类型和参数类型

// Java 每个方法都必须写类型
public UserResponse getUser(Long id) { ... }
//     ↑返回类型        ↑参数类型
# ❌ 禁止
def process(data, flag):
    ...

# ✅ 必须
def process(data: dict, flag: bool) -> ProcessResult:
    ...

4、通过 mypy --strict 检查

翻译

javac = 编译 + 类型检查(二合一)
Python 世界:
  python 解释器 ≈ JVM(只运行,不检查类型)
  mypy ≈ 单独的类型检查工具(只检查,不编译)

mypy --strict src/ 是最强的检查,可以通过三种方式进行:

方式一:命令行指定参数
mypy --strict src/ 
方式二:配置文件
# pyproject.toml
[tool.mypy]
python_version = "3.12"
strict = true
ignore_missing_imports = true
然后运行:
mypy src/  # 自动读取配置文件
方式三:混合使用
配置文件是基础,命令行参数可以覆盖
mypy --strict src/   # 临时开启 strict,覆盖配置文件
mypy --no-strict-optional src/  # 临时关闭某个检查

5、I/O 操作(数据库、HTTP)必须 async/await,不混用同步阻塞调用

翻译:SpringBoot每个请求开启一个线程;FastAPI一个进程一个线程,每个用户访问进入的是同一个线程,需要在I/O操作时让出线程。生产时可通过配置Worker数量去扩充进程。

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐