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

升级Python至3.10.7后PyTest执行完成无法终止问题求助

排查思路与解决办法

1. 检查异步资源未清理

  • 确认测试中所有异步客户端(比如TestClient或自定义aiohttp客户端)都正确调用close():Python 3.10+对异步上下文的处理更严格,未关闭的客户端会残留事件循环资源。
  • 排查测试中是否有未await的异步任务、FastAPIBackgroundTasks:这些任务可能在测试结束后仍后台运行,阻塞事件循环。可在测试末尾强制等待后台任务完成:
    from fastapi import BackgroundTasks
    
    def test_demo():
        tasks = BackgroundTasks()
        # 测试逻辑
        # 强制执行所有后台任务
        for task in tasks.tasks:
            await task()
    
  • 检查自定义异步管理器(如数据库连接池、Redis客户端),测试后需关闭连接池,避免占用事件循环。

2. 验证Pytest插件兼容性

  • 升级测试相关插件到适配Python 3.10的版本:比如pytest-asyncio需确保版本≥0.19.0,旧版本插件可能在新Python版本下出现资源泄漏。
  • 逐个禁用非必要插件排查:用pytest -p no:插件名命令,逐步定位是否是某个插件导致的无法终止问题。

3. 事件循环相关调试

  • 显式指定事件循环策略:在conftest.py中添加固定的事件循环管理逻辑,避免系统默认策略的差异问题:
    import asyncio
    import pytest
    
    @pytest.fixture(scope="session")
    def event_loop():
        policy = asyncio.get_event_loop_policy()
        loop = policy.new_event_loop()
        yield loop
        loop.close()
    
  • 测试结束后检查未完成任务:在teardown阶段添加代码,打印残留任务定位问题:
    import asyncio
    
    def teardown_function():
        loop = asyncio.get_event_loop()
        pending = asyncio.all_tasks(loop)
        if pending:
            print(f"未完成任务列表: {pending}")
            # 强制取消并清理所有任务
            for task in pending:
                task.cancel()
            loop.run_until_complete(asyncio.gather(*pending, return_exceptions=True))
    

4. 升级核心依赖版本

  • 升级FastAPI和Starlette到最新稳定版:Python 3.10对异步语法和事件循环的处理有调整,旧版本框架可能存在兼容性问题,导致资源无法释放。
  • 同步升级其他异步依赖:比如uvicorn、aiohttp、异步版sqlalchemy等,确保所有依赖都适配Python 3.10。

5. CI环境特殊处理

  • Docker容器中检查进程残留:测试结束后用ps aux查看是否有Python进程未退出,可能是后台任务脱离了测试进程。
  • 临时添加强制终止命令:在CI脚本测试步骤后执行pkill -f python作为临时 workaround,找到根本原因后再移除。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 22:05:28