怎么在Python中为pytest用例设置不同执行超时

千辰同学_6756

千辰同学_6756

2026-10-02

667人浏览

原创

pytest-timeout插件提供全局(--timeout)和单例(@pytest.mark.timeout)超时控制,支持signal(默认,Linux/macOS)和thread(Windows/阻塞C扩展)两种中断模式,未安装则配置无效。

怎么在python中为pytest用例设置不同执行超时

用 pytest-timeout 插件设置全局或单个用例超时

pytest 本身不内置超时机制,必须借助 pytest-timeout 插件。它支持两种粒度:整个测试会话(--timeout)和单个用例(@pytest.mark.timeout)。不装这个插件,任何超时配置都无效。

安装命令:pip install pytest-timeout

常见错误现象:加了 @pytest.mark.timeout(5) 却没反应——大概率是插件没装,或 pytest 版本太老(需 ≥ 6.0)。

  • 全局超时:运行 pytest --timeout=10,所有用例超过 10 秒即被 SIGTERM 中断(Linux/macOS)或 TerminateProcess(Windows)
  • 单用例超时:在测试函数上加 @pytest.mark.timeout(3),优先级高于全局值
  • 超时后默认行为是失败并报错 TimeoutError: Test took longer than 3.0 seconds,不会静默跳过

超时模式选 signal 还是 thread?

pytest-timeout 提供两种中断机制:signal(默认,Unix-like 系统)和 thread(Windows 兼容,但有局限)。选错会导致超时不生效或误杀进程。

使用场景决定选择:

  • Linux/macOS + 普通用例 → 用默认 signal 模式,开销低、响应快
  • Windows 或用例里调用了阻塞型 C 扩展(如某些数据库驱动、time.sleep() 在子线程中)→ 必须显式指定 --timeout-method=thread
  • thread 模式无法中断正在执行的 C 函数(比如 requests.get() 底层阻塞),此时需配合 requests 自身的 timeout= 参数

示例:在 Windows 上跑带网络请求的测试,应写成 pytest --timeout=5 --timeout-method=thread,再在代码里补 requests.get(url, timeout=3)。

@pytest.mark.timeout 的参数细节与陷阱

@pytest.mark.timeout 看似简单,但三个参数容易混淆:数值是秒数(float)、method 可覆盖全局模式、func_only 控制是否包含 fixture 执行时间。

python-code-analyz
python-code-analyz

专业Python代码分析与优化,支持语法检查、安全扫描、性能评估、复杂度分析及重构后优化代码生成。

下载
  • 基础写法:@pytest.mark.timeout(2.5) —— 仅限制测试函数体执行时间
  • 含 fixture:@pytest.mark.timeout(5, func_only=False) —— 超时计时从 fixture setup 开始,到 teardown 结束
  • 强制模式:@pytest.mark.timeout(1, method="thread") —— 此用例强制走 thread 模式,无视命令行设置
  • 陷阱:若 fixture 里有长时间阻塞(如启动本地服务),又没设 func_only=False,超时将不覆盖那段耗时,导致“明明设了 1 秒却跑了 20 秒还没中断”

替代方案:不用插件,靠信号或 threading 手动控制

极少数场景(如 CI 环境禁止装第三方插件、或需精确控制中断逻辑),可手动实现超时。但复杂度高,且无法优雅处理 fixture。

核心思路是:在测试函数内起一个监控线程或注册信号处理器,超时后抛出异常或调用 os._exit()(⚠️危险,会跳过 teardown)。

示例(简化版 thread 方案):

import threading
import time
<p>def test_with_manual_timeout():
result = []
def target():
time.sleep(4)  # 模拟慢操作
result.append("done")</p><pre class="brush:php;toolbar:false;">t = threading.Thread(target=target)
t.start()
t.join(timeout=2)
if t.is_alive():
    raise TimeoutError("Manual timeout hit")
assert result == ["done"]

注意:这种写法无法中断 target 中的阻塞调用(如 socket.recv()),且绕过了 pytest 的 fixture 生命周期管理。除非万不得已,别这么干。

真正难的不是设超时,而是判断哪段该被超时覆盖——fixture?网络请求?还是纯计算?漏掉关键环节,超时就形同虚设。

Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!

相关专题

更多
python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

2023.07.20

1631

4

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

2023.07.25

4004

7

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.31

1629

3

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

2023.08.03

23077

23

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

2827

5

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

2867

5

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

1123

5

python合并两个列表
python合并两个列表

Python是一种强大的编程语言,具有许多方便的功能和工具。在Python中,有多种方法可以合并两个列表。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.10

596

4

python是前端还是后端
python是前端还是后端

Python属于前端也属于后端,其灵活性和丰富的生态系统使得开发人员能够在不同的领域中灵活运用。本专题为大家提供python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

2223

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程