Python 开发 面试题¶
涵盖环境工具、类型提示、异步编程、FastAPI、Pydantic、测试、HTTP 客户端。共 140 题:基础 56、进阶 49、高级 35。
基础题(难度:⭐)¶
1. Python 中如何管理依赖?常见工具有哪些?¶
参考答案: pip 安装包并生成 requirements.txt;venv 创建虚拟环境隔离依赖;现代项目用 Poetry/PDM/uv 管理依赖与锁文件,pipenv 较少用。AI 项目常结合 conda 管理 GPU 依赖。
2. venv 与 conda 虚拟环境的区别?¶
参考答案: venv 只隔离 Python 包,轻量标准库自带;conda 既隔离 Python 包也隔离 Python 版本与系统库(如 CUDA),适合数据科学多版本 Python 与 C 依赖场景。
3. 什么是 pyproject.toml?¶
参考答案: PEP 518 引入的项目配置标准文件,统一存放构建系统、项目元数据、依赖、工具配置(black/ruff/mypy),替代 setup.py/requirements 等分散文件。
4. requirements.txt 与 poetry.lock 的区别?¶
参考答案: requirements.txt 只列直接依赖及版本范围,可能不一致;poetry.lock 锁定全部依赖(含子依赖)精确版本,保证团队/生产环境一致可复现。
5. 如何指定 Python 版本?¶
参考答案: pyenv 管理多版本 Python;.python-version 文件指定项目版本;pyproject.toml 的 requires-python 字段声明最低版本;CI 中用 setup-python action。
6. 类型提示(Type Hints)的作用?¶
参考答案: 为变量、参数、返回值标注类型,提升可读性与可维护性;配合 mypy/pyright 静态检查发现 bug;IDE 智能补全;不强制运行时但可用 typing 强制。
7. 写出函数参数与返回值的类型提示示例。¶
参考答案: def greet(name: str, age: int = 0) -> str: return f"Hi {name}"。参数后冒号跟类型,默认值在类型后;返回值用 -> 标注。
8. List、Dict、Tuple、Set 的类型提示怎么写?¶
参考答案: 从 typing 导入或用内置(3.9+):list[str]、dict[str, int]、tuple[int, str]、set[int]。3.9 前需 List[str] 等。
9. Optional[str] 表示什么?¶
参考答案: 表示值可以是 str 或 None。等价于 str | None(3.10+)。常用于可选参数或可能缺失的返回值。
10. Union 类型怎么用?¶
参考答案: Union[int, str] 表示可以是 int 或 str。3.10+ 可用 int | str。适用于联合类型参数。
11. Any 类型表示什么?何时用?¶
参考答案: Any 表示任意类型,不进行静态检查。应少用,仅在类型未知或动态场景(如 JSON 解析中间态)使用,否则丧失类型安全。
12. 类型提示的 TypeVar 是什么?¶
参考答案: 定义泛型类型变量,如 T = TypeVar("T"),使函数保留输入类型:def first(x: list[T]) -> T。泛型容器(Generic)需配合使用。
13. async/await 的基本含义?¶
参考答案: async def 定义协程函数,调用返回协程对象不立即执行;await 挂起当前协程等待 awaitable 完成,事件循环调度其他任务,实现并发 IO。
14. 同步与异步的核心区别?¶
参考答案: 同步阻塞等待 IO 完成才继续,串行低效;异步在 IO 等待时切换执行其他任务,单线程内并发处理多 IO,提升吞吐。CPU 密集仍需多进程。
15. asyncio 的核心组件?¶
参考答案: Event Loop 事件循环调度任务;Coroutine 协程;Task 任务包装协程;Future 底层结果占位;await/async 关键字。asyncio.run() 启动。
16. asyncio.gather 与 asyncio.wait 的区别?¶
参考答案: gather 并发运行多个 awaitable 并按顺序返回结果列表,简单常用;wait 返回 (done, pending) 集合,更灵活可控制超时与首次完成。
17. asyncio.create_task 的作用?¶
参考答案: 将协程包装为 Task 立即调度执行,返回 Task 对象可 await 取结果或取消。是并发执行多协程的标准方式。
18. 什么是协程(Coroutine)?¶
参考答案: 协程是可暂停恢复的函数,由 async def 定义。在 await 处挂起交还事件循环,单线程内多协程协作并发,避免线程切换开销。
19. async with 的作用?¶
参考答案: 异步上下文管理器,进入/退出时执行 aenter/aexit 协程,常用于异步资源(HTTP 连接、数据库连接)的获取与释放。
20. FastAPI 是什么?核心特点?¶
参考答案: 基于 Starlette+Pydantic 的现代异步 Web 框架。特点:类型提示驱动自动文档、异步高性能、依赖注入、自动参数校验、OpenAPI 自动生成。
21. FastAPI 如何定义路由与参数?¶
参考答案: 用装饰器 @app.get("/items/{id}") 定义路由;路径参数 {id}、查询参数(函数参数默认值)、请求体(Pydantic 模型参数)自动解析校验。
22. FastAPI 的依赖注入(Depends)怎么用?¶
参考答案: def get_db(): ...; def items(db=Depends(get_db))。Depends 自动调用依赖函数注入结果,支持嵌套与缓存(同请求内复用),便于数据库会话、鉴权等复用。
23. Pydantic 是什么?解决什么问题?¶
参考答案: 基于 Python 类型提示的数据验证与解析库。自动校验类型、转换类型、抛错,序列化模型,广泛用于配置、API 请求体校验,是 FastAPI 的基石。
24. 写一个简单 Pydantic 模型示例。¶
参考答案: class User(BaseModel): name: str; age: int = 0。继承 BaseModel,字段用类型提示。User(name="Tom") 自动校验,User(name="Tom", age="20") 自动转 int。
25. Pydantic 的 BaseModel 与 dataclass 区别?¶
参考答案: BaseModel 提供校验、序列化、JSON schema、错误处理等丰富功能;dataclass 是标准库轻量数据类,无校验。Pydantic 也提供 @dataclass 装饰器加校验。
26. Pydantic v2 相比 v1 的改进?¶
参考答案: 用 Rust 重写核心(pydantic-core),性能提升 5-50 倍;API 更清晰;改进校验器与序列化器;更好的类型推断; stricter 校验。注意部分 v1 API 不兼容。
27. pytest 的基本用法?¶
参考答案: def test_xxx(): 定义测试函数,assert 断言。pytest 命令自动发现 test_ 开头文件与函数。fixture 共享前置,parametrize 参数化,marker 标记分类。
28. pytest fixture 是什么?¶
参考答案: fixture 提供测试前置数据/资源的函数,用 @pytest.fixture 装饰。测试函数以参数名引用自动注入,支持 scope(function/class/module/session)控制生命周期。
29. 如何参数化 pytest 测试?¶
参考答案: @pytest.mark.parametrize("a,b,expected", [(1,2,3),(4,5,9)]) 装饰测试函数,每条数据生成一个测试用例,便于覆盖多场景。
30. unittest 与 pytest 的区别?¶
参考答案: unittest 标准库,类继承 TestCase,需 self.assertEqual 等;pytest 函数式更简洁,assert 直接用,fixture 灵活,插件丰富。新项目推荐 pytest。
31. requests 库如何发 GET/POST 请求?¶
参考答案: requests.get(url, params={...})、requests.post(url, json={...})。返回 Response 对象,.json() 解析响应体,.status_code 状态码。简单同步。
32. requests 的 Session 有什么用?¶
参考答案: Session 复用 TCP 连接(连接池)、保持 Cookie、统一 headers/认证,多次请求同站点更高效。with requests.Session() as s: 自动关闭。
33. httpx 与 requests 的区别?¶
参考答案: httpx 同时支持同步与异步 API,API 与 requests 类似易迁移,支持 HTTP/2,超时与连接池配置更完善。AI 项目常需异步,httpx 是首选。
34. httpx 如何发异步请求?¶
参考答案: async with httpx.AsyncClient() as client: r = await client.get(url)。AsyncClient 提供异步方法,配合 asyncio 并发多请求,适合高并发场景。
35. 如何设置 HTTP 请求超时?¶
参考答案: requests: requests.get(url, timeout=5);httpx: httpx.Timeout(connect=5, read=10)。建议必设超时防止请求挂起,可分别设连接与读取超时。
36. Python 中如何重试请求?¶
参考答案: tenacity 库 @retry(stop=stop_after_attempt(3), wait=wait_exponential());或自写循环;requests 可配 HTTPAdapter 重连。需区分可重试错误(5xx/超时)与不可重试(4xx)。
37. 什么是上下文管理器(with 语句)?¶
参考答案: with 语句管理资源获取与释放,进入调用 enter,退出(含异常)调用 exit,确保资源正确关闭。如 with open(f) as fh:。
38. 装饰器(Decorator)是什么?¶
参考答案: 装饰器是接收函数返回函数的可调用对象,用 @语法应用,在不改原函数前提下扩展功能。如日志、计时、缓存、鉴权。functools.wraps 保留元信息。
39. 生成器(Generator)与协程关系?¶
参考答案: 生成器用 yield 暂停返回值;协程是增强的生成器,可 yield 接收值(send),是 async/await 底层基础。早期协程基于生成器实现,现代用 async def。
40. Python 的 GIL 是什么?¶
参考答案: Global Interpreter Lock 全局解释器锁,同一时刻只允许一个线程执行 Python 字节码。导致多线程无法利用多核 CPU,CPU 密集任务需用多进程绕过。
41. 多线程、多进程、协程如何选?¶
参考答案: IO 密集用协程(asyncio)或线程;CPU 密集用多进程(绕过 GIL);混合任务可进程+协程。AI 应用多为 IO 密集(等 LLM API),协程最优。
42. 如何捕获与处理异常?¶
参考答案: try: ... except SpecificError as e: ... else: ... finally: ...。捕获具体异常而非裸 except;finally 释放资源;可自定义异常类继承 Exception。
43. logging 模块的基本用法?¶
参考答案: import logging; logging.basicConfig(level=INFO); logging.info("msg")。可配置 handler(文件/控制台)、formatter、级别。生产用 dictConfig 或第三方 loguru/structlog。
44. f-string 的基本用法?¶
参考答案: f"Hello {name}, age {age+1}"。在字符串中嵌入表达式,简洁高效。3.8+ 支持 f"{x=}" 调试输出变量名与值。3.12+ 支持嵌套引号。
45. 列表推导式与生成器表达式区别?¶
参考答案: 列表推导 [x*2 for x in range(10)] 一次性生成列表占内存;生成器表达式 (x*2 for x in range(10)) 惰性迭代省内存,适合大数据流处理。
46. 字典推导式怎么写?¶
参考答案: {k: v for k, v in items if condition}。如 {name: age for name, age in people if age > 18}。也可用于反转字典 {v:k for k,v in d.items()}。
47. Python 的可变与不可变类型?¶
参考答案: 不可变:int/str/tuple/frozenset,修改会创建新对象;可变:list/dict/set,原地修改。函数默认参数避免用可变对象(如 def f(x=[]))防共享状态 bug。
48. 深拷贝与浅拷贝区别?¶
参考答案: 浅拷贝 copy.copy 复制外层,内层仍引用原对象;深拷贝 copy.deepcopy 递归复制全部层级。嵌套可变对象修改时浅拷贝会影响原对象,需深拷贝。
49. args 和 *kwargs 的含义?¶
参考答案: args 收集多余位置参数为元组;kwargs 收集多余关键字参数为字典。常用于灵活函数签名、装饰器转发参数。顺序:位置参数、args、关键字参数、**kwargs。
50. 如何读取与解析 JSON?¶
参考答案: import json; json.loads(json_str) 解析字符串为对象;json.dumps(obj) 序列化为字符串。文件用 json.load(f)/json.dump(obj, f)。AI 应用大量用 JSON 与 LLM 交互。
51. 如何读取与写入文件?¶
参考答案: with open(path, "r", encoding="utf-8") as f: content = f.read()。with 自动关闭。写用 "w" 覆盖/"a" 追加,f.write(text)。务必指定 encoding 防编码问题。
52. pathlib 相比 os.path 的优势?¶
参考答案: pathlib 面向对象,链式操作更优雅:Path("a")/"b"/"c.txt"。提供 .read_text()/.glob() 等便捷方法,跨平台路径分隔符自动处理。新项目推荐。
53. 如何遍历目录查找文件?¶
参考答案: Path(".").rglob("*.py") 递归查找;或 Path(".").glob("*.py") 当前层。也可用 os.walk。pathlib 更简洁。
54. 什么是 dataclass?¶
参考答案: @dataclass 装饰器自动生成 init/repr/eq 等方法的数据类。简化样板代码,支持默认值、类型提示、frozen 不可变。轻量数据载体。
55. enum 枚举怎么用?¶
参考答案: class Color(Enum): RED=1; BLUE=2。用 Color.RED 引用,避免魔法值,提升可读性与安全。StrEnum(3.11+)适合字符串枚举如状态机。
56. 如何在 Python 中执行系统命令?¶
参考答案: subprocess.run(["cmd", "arg"], capture_output=True, text=True) 安全推荐;避免 os.system(无输出控制、shell 注入风险)。参数用列表防注入,shell=True 慎用。
进阶题(难度:⭐⭐)¶
1. 解释 asyncio 事件循环的工作原理。¶
参考答案: 事件循环维护就绪回调队列与定时器,循环执行:运行就绪回调→等待 IO 就绪→将 IO 回调加入就绪→处理定时器。协程在 await 处交还控制权,事件循环调度其他任务,单线程并发。
2. asyncio 中如何限制并发数?¶
参考答案: asyncio.Semaphore 信号量限制同时执行数:sem = Semaphore(10); async with sem: ...。或用第三方 aiometer/aiohttp 的连接池。防止打爆下游 API。
3. async for 与 async with 的使用场景?¶
参考答案: async for 迭代异步可迭代对象(如流式响应逐块读取);async with 管理异步资源(如 HTTP 客户端、数据库连接)。都需要 await 底层支持。
4. 如何在异步代码中调用同步阻塞函数?¶
参考答案: 用 await asyncio.to_thread(blocking_func, args) 在线程池执行避免阻塞事件循环;或 loop.run_in_executor。CPU 密集用 ProcessPoolExecutor。注意 GIL。
5. 如何在同步代码中调用异步函数?¶
参考答案: asyncio.run(coro) 启动事件循环运行单个协程;或获取已有 loop 调 loop.run_until_complete()。避免嵌套事件循环(如 Jupyter 需 nest_asyncio)。
6. FastAPI 的 ASGI 与 WSGI 区别?¶
参考答案: WSGI 同步模型,一个请求一个 worker,不支持异步与长连接;ASGI 异步模型,支持 WebSocket、SSE、流式响应,单 worker 并发多请求。FastAPI 基于 ASGI(Starlette)。
7. FastAPI 如何处理流式响应(SSE)?¶
参考答案: 返回 StreamingResponse(generator, media_type="text/event-stream"),生成器 yield 数据块。常配合 LLM 流式输出,前端 EventSource 接收。
8. FastAPI 中 BackgroundTasks 的作用与限制?¶
参考答案: BackgroundTasks 在响应后执行后台任务(如发邮件、写日志),简单易用。限制:同进程内执行、失败不影响响应、不适合长任务与重试,复杂场景用 Celery/RQ。
9. FastAPI 的中间件(Middleware)怎么写?¶
参考答案: @app.middleware("http") async def mw(request, call_next): ...; response = await call_next(request); ...; return response。可在请求前后处理,如日志、CORS、计时、鉴权。
10. FastAPI 如何做异常处理与统一错误响应?¶
参考答案: 自定义异常类继承 Exception;用 @app.exception_handler(MyError) 注册处理器返回 JSONResponse。也可全局捕获 Exception 兜底,统一错误码与格式。
11. FastAPI 项目如何组织结构?¶
参考答案: 推荐分层:routers(路由)、schemas(Pydantic 模型)、models(ORM)、services(业务逻辑)、crud(数据访问)、core(配置/安全/依赖)。main.py 装配。便于维护测试。
12. Pydantic 模型的嵌套校验如何实现?¶
参考答案: 字段类型用另一个 BaseModel:class Order(BaseModel): items: list[Item]。Pydantic 递归校验嵌套结构,错误路径精确到字段,适合复杂 API 请求体。
13. Pydantic 的 Field、validator、field_validator 区别?¶
参考答案: Field 配置字段元数据(默认、约束、描述);@validator(v1)类方法校验字段;@field_validator(v2)校验单/多字段;@model_validator 校验整个模型。v2 推荐 field_validator。
14. Pydantic 如何自定义校验逻辑?¶
参考答案: v2 用 @field_validator("email") 装饰类方法,参数为值,返回校验后值或抛 ValueError。@model_validator(mode="after") 校验跨字段约束。可复用 Annotated+AfterValidator。
15. Pydantic 的序列化与 .model_dump()?¶
参考答案: model.model_dump() 转字典,.model_dump_json() 转 JSON 字符串。支持 exclude/include 指定字段、by_alias 别名、exclude_none 等。v1 用 .dict()/.json()(已弃用)。
16. Pydantic Settings 如何管理配置?¶
参考答案: 继承 BaseSettings,字段自动从环境变量读取(大小写不敏感)。支持嵌套、.env 文件(model_config=SettingsConfigDict(env_file=".env"))、别名、默认值。统一管理应用配置。
17. Pydantic 的 Generic 泛型模型怎么写?¶
参考答案: T = TypeVar("T"); class Response(BaseModel, Generic[T]): data: T。实例化 Response[int](data=1)。常用于通用 API 响应包装。
18. Pydantic 如何处理 Union 与 discriminators?¶
参考答案: Union 多类型按顺序尝试解析;discriminator 指定区分字段:Union[Cat, Dog] = Field(discriminator="type"),按 type 字段选模型,避免歧义,提升性能。
19. Pydantic 的 computed_field 是什么?¶
参考答案: @computed_field 装饰 @property,使其在 model_dump/序列化时输出,但不是存储字段。适合派生属性如全名、状态判断。
20. pytest 如何 mock 依赖?¶
参考答案: 用 monkeypatch fixture 替换函数/属性:monkeypatch.setattr(module, "func", mock_func);或 unittest.mock.patch 装饰器;pytest-mock 提供 mocker.fixture 更简洁。
21. pytest 如何测试异步函数?¶
参考答案: 安装 pytest-asyncio,标记 @pytest.mark.asyncio,测试函数用 async def 即可 await。配置 asyncio_mode=auto 自动标记。anyio 也提供类似插件。
22. 如何测量测试覆盖率?¶
参考答案: pytest-cov 插件:pytest --cov=src --cov-report=html。生成 HTML 报告查看行/分支覆盖。目标通常 80%+,关键路径 100%,但应关注质量非数字。
23. mock 与 patch 的区别?¶
参考答案: patch 是替换目标的操作(装饰器或上下文),mock 是替换后的假对象。patch 默认返回 MagicMock。可配置 return_value/side_effect/assert_called_with 验证调用。
24. 如何测试调用外部 API 的代码?¶
参考答案: mock HTTP 客户端(requests/httpx)返回预设响应;或用 responses/respx 库注册 URL 模拟响应;或用 VCR.py 录制回放真实请求。避免真实网络,保证测试稳定快速。
25. httpx 的连接池如何配置?¶
参考答案: httpx.AsyncClient(limits=httpx.Limits(max_connections=100, max_keepalive_connections=20), timeout=httpx.Timeout(10))。合理配置避免连接耗尽与超时。
26. httpx 如何发送流式请求处理大响应?¶
参考答案: async with client.stream("GET", url) as resp: async for chunk in resp.aiter_bytes(): ...。流式读取避免一次性加载大响应到内存,适合 LLM 流式输出与大文件下载。
27. 如何在 httpx 中添加鉴权与拦截器?¶
参考答案: 鉴权:auth=httpx.BasicAuth(user, pwd) 或 headers 加 Token;事件钩子 hooks={"request":[...], "response":[...]};或自定义 httpx.Auth 实现刷新 token。
28. tenacity 的重试策略如何配置?¶
参考答案: @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, max=10), retry=retry_if_exception_type((Timeout, ConnectionError)))。可组合停止、等待、重试条件,支持 before/after 日志。
29. 如何优雅地取消协程任务?¶
参考答案: task.cancel() 触发 CancelledError;协程内 try/finally 释放资源;await 时检查取消。asyncio.gather(return_exceptions=True) 防一个失败影响全部。注意屏蔽取消传播。
30. asyncio 的 Lock/Semaphore/Queue 作用?¶
参考答案: Lock 互斥访问共享资源;Semaphore 限制并发数;Queue 协程间安全传递数据(生产者-消费者)。均为异步版本,需 await,不能与线程版混用。
31. 如何在 FastAPI 中实现依赖缓存?¶
参考答案: Depends 默认同请求内缓存(同依赖只执行一次);跨请求用 lru_cache 装饰依赖函数缓存;或自定义带 TTL 的缓存依赖。注意缓存失效与并发更新。
32. FastAPI 的 Security 与 OAuth2 怎么用?¶
参考答案: fastapi.security 提供 OAuth2PasswordBearer 等;token: str = Depends(oauth2_scheme) 提取 token;自定义依赖校验返回用户。Swagger 自动显示登录按钮。
33. Pydantic v2 的 ConfigDict 常用项?¶
参考答案: model_config = ConfigDict(str_strip_whitespace=True, frozen=True, extra="forbid", populate_by_name=True)。控制行为:去空白、不可变、禁止额外字段、允许别名赋值。
34. Pydantic 的 TypeAdapter 是什么?¶
参考答案: TypeAdapter 为任意类型(非 BaseModel)提供校验与序列化,如 TypeAdapter(list[int]).validate_python([...])。v2 新增,替代 v1 的 parse_obj_as。
35. 如何用 Pydantic 解析 LLM 输出的 JSON?¶
参考答案: 定义目标 BaseModel;用 Model.model_validate_json(text) 或先 json.loads 再 model_validate。配合响应格式约束与重试,解析失败时反馈让 LLM 修复。
36. pytest conftest.py 的作用?¶
参考答案: conftest.py 定义共享 fixture、hooks、markers,自动被同目录及子目录测试发现,无需导入。适合放数据库会话、测试客户端、临时目录等公共 fixture。
37. 如何给 FastAPI 写集成测试?¶
参考答案: 用 httpx.AsyncClient(app=app, base_url="...") 或 TestClient(app) 发请求测端到端;mock 外部依赖(DB/LLM);fixture 准备数据;测试主要场景与边界。ASGI transport 不占端口。
38. Python 类型系统的协变与逆变?¶
参考答案: 协变:子类型关系保持(list[Dog] 是 list[Animal] 的子类型,但 Python list 不变);逆变:参数类型反向。Python 默认不变,用 TypeVar 协变(T_co)/逆变(T_contra)声明。
39. Protocol(结构化子类型)是什么?¶
参考答案: typing.Protocol 定义鸭子类型接口,类无需显式继承只要实现方法即满足。便于解耦与依赖抽象,配合 mypy 静态检查,是 Python 的"接口"。
40. typing 的 Literal、Final、TypedDict?¶
参考答案: Literal 限定字面值(如状态枚举);Final 防止重写;TypedDict 给字典键值类型化(如 {"name": str, "age": int}),适合 JSON 结构类型化而不建模型。
41. 如何用 Pydantic 处理动态/部分未知字段?¶
参考答案: model_config = ConfigDict(extra="allow") 保留额外字段到 model_extra;或用 dict[str, Any] 类型字段;或自定义 init 解析。注意校验与序列化。
42. Python 的 weakref 有什么用?¶
参考答案: weakref 创建对象弱引用不增加引用计数,对象可被回收。用于缓存(避免内存泄漏)、观察者模式。WeakValueDictionary/WeakSet 自动清理失效引用。
43. 解释 functools.lru_cache 与缓存策略。¶
参考答案: @lru_cache(maxsize=128) 缓存函数结果按参数命中,LRU 淘汰。适合纯函数无副作用。注意不可变参数、缓存失效(cachetools 的 TTLCache 适合带过期)。
44. 如何实现异步的 LRU 缓存?¶
参考答案: functools.lru_cache 不支持协程(缓存的是协程对象)。可用 cachetools.AsyncLRUCache,或自建 dict 缓存 await 结果,配合 asyncio.Lock 防缓存击穿。
45. Python 的 import 机制与循环导入?¶
参考答案: import 按 sys.modules 缓存查找模块。循环导入(A import B, B import A)可能报错。解决:延迟导入(函数内导入)、重构拆分、合并到公共模块、用 TYPE_CHECKING 处理类型。
46. 解释 if name == "main" 的作用。¶
参考答案: 判断模块是否直接运行(而非被导入)。直接运行时 name 为 "main",执行入口代码;被导入时不执行,便于模块既可独立运行又可被复用。
47. pydantic-settings 如何加载多源配置优先级?¶
参考答案: 优先级(高→低):初始化参数 > 环境变量 > .env 文件 > 代码默认值。可通过 customise_sources 自定义顺序与来源(如加 consul/etcd),适配复杂配置场景。
48. structlog/loguru 相比标准 logging 的优势?¶
参考答案: structlog 输出结构化日志(JSON)便于聚合分析,支持上下文绑定;loguru 开箱即用、API 简洁、支持 rotate/异步/彩色。生产可观测推荐 structlog+JSON,开发用 loguru。
49. 如何用 Python 实现 API 限流?¶
参考答案: 令牌桶/漏桶算法;slowapi 库集成 FastAPI;或 Redis+lua 实现分布式限流;按用户/IP/API 维度。AI 应用常按 token/请求维度限流防滥用与控成本。
高级题(难度:⭐⭐⭐)¶
1. 分析 asyncio 的事件循环在多线程下的使用注意点。¶
参考答案: 每个线程需有自己的事件循环(loop.run_until_complete 或 asyncio.run);跨线程调度用 asyncio.run_coroutine_threadsafe(coro, loop) 提交到目标 loop;不要在不同线程共享 loop。多线程协程混合需谨慎设计。
2. 如何排查事件循环阻塞问题?¶
参考答案: 现象:所有协程卡住、延迟飙升。排查:用 py-spy/austin 采样定位阻塞函数;检查是否有同步 IO/CPU 密集未 to_thread;aiomonitor 在线查看任务;设置 slow callback 警告(loop.slow_callback_duration)。
3. 设计一个支持流式输出与工具调用的 FastAPI Agent 接口。¶
参考答案: StreamingResponse + SSE 推送 Token;定义事件类型(token/tool_call/tool_result/done);工具调用时发 tool_call 事件前端展示,后端执行后发 tool_result 再继续;前端按事件类型增量渲染,支持中断。
4. FastAPI 高并发场景下如何优化性能?¶
参考答案: 异步 IO 不阻塞 loop;uvicorn/gunicorn 多 worker 利用多核;连接池复用 DB/HTTP;缓存热数据;限流保护;水平扩展无状态服务;异步任务剥离到队列;profiling 定位瓶颈。
5. 如何设计 FastAPI 的优雅关闭?¶
参考答案: 捕获 lifespan 的 shutdown 事件;停止接收新请求;等待进行中请求完成(超时强制断);关闭连接池、数据库会话、消息队列消费者;清理临时资源。uvicorn 配置 timeout-graceful-shutdown。
6. Pydantic v2 性能优化的关键点?¶
参考答案: 用 Rust 核心默认快;避免冗余 validator;model_config 选合适的 extra 策略;批量用 TypeAdapter 替代多次 model_validate;复用 schema 缓存;避免运行时动态模型生成。
7. 如何在 Pydantic 中实现版本化 API 模型兼容?¶
参考答案: 多版本模型类(UserV1/UserV2);discriminator 区分;自定义迁移方法转换版本;字段加 alias 兼容旧名;extra="allow" 容忍新字段;序列化时按版本选择字段输出。
8. 设计一个健壮的 LLM 客户端封装。¶
参考答案: 封装超时、重试(tenacity 区分错误)、限流(信号量)、熔断(pybreaker)、缓存、指标(延迟/Token/错误)、多模型路由降级、流式与结构化输出、密钥管理与轮换、可观测日志。线程/协程安全。
9. 如何实现异步代码的并发控制与背压?¶
参考答案: Semaphore 限并发;asyncio.Queue 设 maxsize 实现背压,生产者阻塞防淹没消费者;令牌桶限速;拒绝策略(拒绝/排队/降级);监控队列长度告警。保护下游与自身。
10. 分析 Python 多进程与协程在 AI 推理服务的取舍。¶
参考答案: LLM API 调用是 IO 密集,协程最优;本地模型推理是 CPU/GPU 密集,需多进程或多 worker,GIL 限制多线程。混合:协程处理请求编排,推理任务提交进程池/GPU 队列异步执行。
11. 如何在测试中模拟 LLM 的不确定性?¶
参考答案: mock 时配置 side_effect 返回多组不同响应模拟变化;用 property-based testing(hypothesis)生成多样输入;混沌测试注入错误(超时/格式错);录制真实响应回放。验证代码鲁棒性。
12. 设计一个可扩展的 Agent 框架代码结构。¶
参考答案: 抽象 Agent 基类(run/step/observe);工具注册器与协议(Tool Protocol);记忆抽象(短期/长期);模型客户端接口;运行器编排循环;配置驱动(YAML/Pydantic);插件化扩展。依赖注入解耦。
13. 如何处理 Pydantic 模型与 ORM 模型的转换?¶
参考答案: 分层:Pydantic schema(API 层)与 ORM model(数据层)分离;用 model_validate 或 from_orm(v2: model_validate)转换;避免循环引用;敏感字段不暴露;可用 SQLModel 合并简化。
14. 分析 asyncio 的 Future 与 Task 区别与协程关系。¶
参考答案: Future 是底层结果占位,由 IO 回调 set_result;Task 是 Future 子类,包装协程由事件循环驱动执行;协程需 create_task 才被调度。await 本质等待 awaitable(Future/Task/协程)完成。
15. 如何实现 Python 应用的分布式追踪?¶
参考答案: OpenTelemetry SDK 自动/手动埋点;FastAPI 中间件提取传播 trace 上下文;跨服务 HTTP 头传递(W3C traceparent);异步上下文用 contextvar 传播;导出到 Jaeger/Tempo;关联日志与 trace_id。
16. 设计一个支持断点续传的 Agent 任务系统。¶
参考答案: 每步持久化状态到 DB/Redis(checkpoint);任务 ID 关联状态;恢复时加载最新 checkpoint 续跑;幂等步骤支持重放;失败步骤重试;超时检测重启;前端轮询或 SSE 获取进度。
17. 如何优化 Python 应用启动速度?¶
参考答案: 延迟导入重模块;预编译(pyc);冷启动用 serverless 注意依赖体积;缓存初始化结果;并行初始化各组件;减少启动时同步 IO;用 gunicorn preload 加载应用;按需加载模型。
18. 分析 GIL 对多线程 LLM 客户端的影响。¶
参考答案: LLM 客户端主要等网络 IO,GIL 在 IO 等待时释放,多线程/协程均可并发;但 JSON 解析、加密等 CPU 操作受 GIL 限制。协程开销更小更适合高并发,多线程可与同步库混用。
19. 如何设计支持多租户的 FastAPI 应用?¶
参考答案: 请求中间件提取 tenant_id;依赖注入提供租户隔离的 DB/存储客户端;数据层强制 tenant 过滤;配额与限流按租户;密钥按租户管理;日志加 tenant 上下文;资源隔离(schema/库/前缀)。
20. 实现一个通用的重试与退避装饰器。¶
参考答案: 装饰器捕获指定异常,循环重试至 max_attempts;退避用指数+抖动(random)防惊群;区分可重试(网络/5xx)与不可重试(4xx);记录重试日志;支持回调钩子。生产用 tenacity 更稳。
21. 如何处理大规模并发下的连接池耗尽?¶
参考答案: 监控连接池使用率;合理设 max_connections;按优先级分配;队列化请求背压;连接超时与回收;分片多池;降级非核心请求;限流保护;异步 IO 减少连接持有时间。
22. 设计 Pydantic 模型的演进与数据迁移策略。¶
参考答案: 字段新增给默认值保兼容;删除字段先标记 deprecated;类型变更用版本化模型或自定义校验兼容旧格式;迁移脚本批量转换存量数据;契约测试防破坏性变更;文档维护 changelog。
23. 分析 asyncio 的调试技巧。¶
参考答案: asyncio.run(debug=True) 开启调试,报告慢回调与未处理异常;loop.set_debug(True);PYTHONASYNCIODEBUG 环境变量;aiomonitor 在线查看;用 logging 抓 coroutine never awaited 警告。
24. 如何在 Agent 中实现安全的代码执行沙箱?¶
参考答案: 隔离环境:Docker 容器、gVisor、Firecracker 微 VM;限制资源(CPU/内存/时间/网络);无权限用户运行;只读文件系统;gVisor/NSJail 系统调用过滤;超时杀死;输出大小限制。避免 exec 直接跑。
25. 设计一个支持 A/B 测试的 LLM 应用框架。¶
参考答案: 配置中心管理实验(流量分桶、模型/Prompt 变体);请求按用户哈希分流;统一指标采集(质量、延迟、成本);统计显著性检验;灰度渐进放量;一键回滚。隔离实验配置避免相互干扰。
26. 如何实现 Pydantic 模型的深拷贝与不可变性保障?¶
参考答案: model_copy(deep=True) 深拷贝;model_config=frozen=True 使实例不可变(赋值报错);字段用 immutable 类型(tuple 替代 list);自定义 setattr 拦截。配合 hash 与缓存。
27. 分析 Python 应用的内存泄漏排查方法。¶
参考答案: tracemalloc 跟踪分配快照对比;objgraph 找增长对象与引用链;gc 模块检查不可达对象;memory_profiler 行级分析;容器内持续监控 RSS;常见原因:全局缓存无淘汰、闭包引用、循环引用无 del。
28. 如何在异步框架中实现数据库访问?¶
参考答案: 用异步驱动:asyncpg(PostgreSQL)、aiomysql、SQLAlchemy 2.0 async、SQLModel;连接池管理;session 生命周期绑定请求;避免阻塞操作;事务用 async with;N+1 用 selectinload 预加载。
29. 设计一个 Agent 工具调用的统一抽象层。¶
参考答案: 定义 Tool Protocol(name/description/params_schema/run);同步与异步 run;输入输出 Pydantic 校验;错误标准化;超时与重试;权限标注;OpenAPI/Function Schema 自动生成;注册中心按名查找。
30. 如何优化 Pydantic 模型在热路径的性能?¶
参考答案: 避免在循环内重复创建/校验;缓存序列化结果;用 model_construct 跳过校验(已信任数据);减少嵌套层级;预编译 schema;批量用 TypeAdapter;关闭不必要的 validator;用 slots 或 dataclass 替代。
31. 分析 FastAPI 中 Depends 的实现原理与缓存机制。¶
参考答案: Depends 是声明式依赖标记,框架在请求时按依赖图解析执行;同请求内同依赖实例缓存(基于 callable 标识),避免重复执行;use_cache=False 可禁用;支持嵌套依赖与 yield 清理资源。
32. 如何实现跨进程的异步任务队列?¶
参考答案: Celery(功能全但同步为主,需 gevent/eventlet)、RQ、ARQ(原生 asyncio 基于 Redis)、Dramatiq、Celery 5+ 部分支持异步。AI 长任务用队列剥离主流程,支持重试、优先级、定时。
33. 设计一个支持多模型的统一 LLM 客户端接口。¶
参考答案: 抽象 LLMClient Protocol(complete/chat/embed/stream);各厂商适配器实现;统一消息/工具/响应格式;配置驱动选择;特性检测(是否支持工具/视觉);降级与路由;成本与延迟统计。LiteLLM 是参考实现。
34. 如何在测试中验证异步并发正确性?¶
参考答案: 注入随机延迟与错误模拟真实;断言并发结果与串行一致(线性化);用 asyncio.gather 并发多请求测竞争;mock 信号量验证限流;压力测试找瓶颈;监控竞态条件与死锁;用 pytest-asyncio 的并发 fixture。
35. 分析 Python 3.12+ 对异步与类型的改进对 AI 开发的影响。¶
参考答案: 更快的启动与执行;TaskGroup 与 ExceptionGroup 简化并发错误处理;改进的类型系统(Self、override 装饰器);PEP 695 泛型新语法;性能提升降低推理服务成本。应跟进新特性提升代码质量与性能。