使 Python 单元测试因任何线程的异常而失败

2024-04-02

我正在使用单元测试框架来自动化多线程 python 代码、外部硬件和嵌入式 C 的集成测试。尽管我公然滥用单元测试框架进行集成测试,但它的效果非常好。除了一个问题:如果任何生成的线程引发异常,我需要测试失败。这可以通过单元测试框架实现吗?

一个简单但不可行的解决方案是 a) 重构代码以避免多线程或 b) 单独测试每个线程。我不能这样做,因为代码与外部硬件异步交互。我还考虑过实现某种消息传递以将异常转发到主单元测试线程。这将需要对正在测试的代码进行与测试相关的重大更改,我想避免这种情况。

是时候举个例子了。我可以修改下面的测试脚本以在 my_thread 中引发的异常上失败吗without修改 x.ExceptionRaiser 类?

import unittest
import x

class Test(unittest.TestCase):
    def test_x(self):
        my_thread = x.ExceptionRaiser()
        # Test case should fail when thread is started and raises
        # an exception.
        my_thread.start()
        my_thread.join()

if __name__ == '__main__':
    unittest.main()

首先,sys.excepthook看起来像是一个解决方案。它是一个全局钩子,每次抛出未捕获的异常时都会调用它。

不幸的是,这不起作用。为什么?出色地threading包裹你的run代码中的函数打印您在屏幕上看到的可爱的回溯(注意到它总是告诉您Exception in thread {Name of your thread here}?这就是它的完成方式)。

从 Python 3.8 开始,您可以重写一个函数来实现此功能:线程.excepthook https://docs.python.org/3/library/threading.html#threading.excepthook

...可以重写 threading.excepthook() 以控制如何处理 Thread.run() 引发的未捕获异常

那么我们该怎么办?用我们的逻辑替换这个函数,并且voilà:

对于Python >= 3.8

import traceback
import threading 
import os


class GlobalExceptionWatcher(object):
    def _store_excepthook(self, args):
        '''
        Uses as an exception handlers which stores any uncaught exceptions.
        '''
        self.__org_hook(args)
        formated_exc = traceback.format_exception(args.exc_type, args.exc_value, args.exc_traceback)
        self._exceptions.append('\n'.join(formated_exc))
        return formated_exc

    def __enter__(self):
        '''
        Register us to the hook.
        '''
        self._exceptions = []
        self.__org_hook = threading.excepthook
        threading.excepthook = self._store_excepthook

    def __exit__(self, type, value, traceback):
        '''
        Remove us from the hook, assure no exception were thrown.
        '''
        threading.excepthook = self.__org_hook
        if len(self._exceptions) != 0:
            tracebacks = os.linesep.join(self._exceptions)
            raise Exception(f'Exceptions in other threads: {tracebacks}')

对于旧版本的 Python,这有点复杂。 长话短说,看来threadingnodule 有一个未记录的导入,它执行以下操作:

threading._format_exc = traceback.format_exc

毫不奇怪,只有当线程抛出异常时才会调用该函数run功能。

所以对于 python

import threading 
import os

class GlobalExceptionWatcher(object):
    def _store_excepthook(self):
        '''
        Uses as an exception handlers which stores any uncaught exceptions.
        '''
        formated_exc = self.__org_hook()
        self._exceptions.append(formated_exc)
        return formated_exc
        
    def __enter__(self):
        '''
        Register us to the hook.
        '''
        self._exceptions = []
        self.__org_hook = threading._format_exc
        threading._format_exc = self._store_excepthook
        
    def __exit__(self, type, value, traceback):
        '''
        Remove us from the hook, assure no exception were thrown.
        '''
        threading._format_exc = self.__org_hook
        if len(self._exceptions) != 0:
            tracebacks = os.linesep.join(self._exceptions)
            raise Exception('Exceptions in other threads: %s' % tracebacks)

Usage:

my_thread = x.ExceptionRaiser()
# will fail when thread is started and raises an exception.
with GlobalExceptionWatcher():
    my_thread.start()
    my_thread.join()
            

你还需要join你自己,但在退出时,with语句的上下文管理器将检查其他线程中抛出的任何异常,并适当地引发异常。


本代码“按原样”提供,不提供任何形式的保证, 明示或暗示

这是一个没有记录的、有点可怕的黑客行为。我在linux和windows上测试了它,似乎可以工作。需要您自担风险使用它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使 Python 单元测试因任何线程的异常而失败 的相关文章

  • Pandas:向量化局部范围操作([i:i+2] 行的最大值和总和)

    我希望在数据帧中的每一行的局部范围内进行计算 同时避免速度缓慢for环形 例如 对于下面数据中的每一行 我想找到未来 3 天内 包括当天 的最高气温以及未来 3 天内的总降雨量 Day Temperature Rain 0 30 4 1 3
  • Mac 上的 Errno 13 权限被拒绝

    我只是测试如何从一个 py 文件调用外部 py 文件 我有 2 个 py 文件 都在同一目录中 这是主要代码 runext py 假设调用 ext py import subprocess subprocess call Users tra
  • 使用 Matplotlib、PyQt 和 Threading 进行实时绘图导致 python 崩溃

    我一直在努力研究我的 Python 应用程序 但找不到任何答案 我有 PyQT GUI 应用程序 它使用 Matplotlib 小部件 GUI 启动一个新线程来处理 mpl 小部件的绘图 恐怕我现在通过从另一个线程访问 matplotlib
  • pip-tools 的干净设置不会编译非常基本的 pyproject.toml

    使用全新的pip tools设置总是会导致Backend subprocess exited error pyproject toml project dependencies openpyxl gt 3 0 9 lt 4 在仅包含上述 p
  • 安装python启动文件

    我如何安装pythonstartup文件 以便它在命令上运行 例如python myfile py 我尝试将其安装到我的 home myuserUbuntu的目录 但它说我没有足够的权限 此外 不同的地方交替说它应该全部大写或全部小写 前面
  • 使用多行选项和编码选项读取 CSV

    在 azure Databricks 中 当我使用以下命令读取 CSV 文件时multiline true and encoding SJIS 似乎编码选项被忽略了 如果我使用multiline选项 Spark 使用默认值encoding那
  • Tensorboard——High-level节点的计算时间与其子节点计算时间的总和不同

    继tutorial https www tensorflow org programmers guide graph viz在 TensorFlow 上 我试图使用张量板来理解运行时统计数据 我发现代表名称范围的高级节点的计算时间不等于其子
  • 磁盘寻道时间测量方法

    我编写了一个脚本来测量 HDD 上的寻道时间 并且其完成方式的微小变化会导致显着不同的时间 第一个周期在磁盘开头的区域内进行跳转 第二个周期选择磁盘上执行查找的随机区域 相同大小 这种方法显然不同 但我不明白为什么它会改变结果 请注意 对于
  • “ModuleNotFoundError:我的 Docker 容器中没有名为 的模块”

    我正在尝试在 Docker 容器中运行 python 脚本 但我不知道为什么 python 找不到任何 python 模块 我认为它与 PYTHONPATH 环境变量有关 所以我尝试将其添加到 Dockerfile 中 如下所示 ENV P
  • Pymongo 批量插入

    我正在尝试批量插入文档 但批量插入时不会插入超过 84 个文档 给我这个错误 in insert pymongo errors InvalidOperation cannot do an empty bulk insert 是否可以批量插入
  • ctypes 加载 dll 时没有错误消息,但什么也没发生

    我尝试在ctypes中使用windll LoadLibrary将dll文件导入python 尽管没有任何错误消息 但头文件中列出的函数似乎都没有成功加载 我想知道是dll文件有问题 还是我错误地使用了windll LoadLibrary方法
  • 如何从 Android 调用 RESTful 方法?

    我尝试了两种不同的方法来从 Android 调用简单的 REST 方法 所述 REST 方法 适用于其他客户端 仅返回一个 int val 例如 17 以下两次尝试都是基于我在网上找到的代码 有一种是这样的 公共无效onFetchBtnCl
  • 我应该使用课程吗? (Python)

    我正在尝试编写一个包含一些数学函数的小型 Python 模块 例如 它可能包含如下函数 def quad x a b c return a x 2 b x c 您可能会注意到它包含几个参数 即a b c 除了变量x 现在 如果我将其放入文件
  • django.core.exceptions.FieldDoesNotExist:模型没有名为 的字段

    经过一番谷歌搜索后只找到了一个死胡同的话题 https stackoverflow com questions 23356211 django south migration is throwing an error module obje
  • pyspark 中的 Pandas UDF

    我正在尝试在 Spark 数据帧上填充一系列观察结果 基本上我有一个日期列表 我应该为每个组创建缺失的日期 在熊猫中有reindex函数 这是 pyspark 中不可用的 我尝试实现 pandas UDF pandas udf schema
  • 使用 ctypes 映射共享库中的全局变量

    我想映射一个 int 值pbs errno在库中声明为全局libtorque so使用ctypes 目前我可以像这样加载库 from ctypes import libtorque CDLL libtorque so 并成功映射了一堆功能
  • 卸载我安装的所有 Python 包及其依赖项,而不用破坏我的 Mac

    有很多问题 但正确的方法似乎是手动卸载不需要的所有内容 pip 在卸载时不会卸载包的依赖项 https stackoverflow com questions 7915998 does uninstalling a package with
  • 在Python中检测re(regexp)对象

    我想知道什么是正确的 pythonic 向后和向前兼容的方法如何检查对象是否已编译re object isinstance方法不能轻易使用 而生成的对象声称是 sre SRE Pattern object gt gt gt import r
  • 添加和访问 numpy 结构化数组的对象类型字段

    我正在使用 numpy 1 16 2 简单来说 我想知道如何将对象类型字段添加到结构化数组中 标准方式通过recfunctions模块抛出错误 我想这是有原因的 因此 我想知道我的解决方法是否有问题 此外 我想了解为什么这种解决方法是必要的
  • 使用 python 在一个 html 页面中显示分割数据框的 HTML 代码

    我是 html css 新手 所以对以 html 格式显示的数据有疑问 我有一个很长的列表 我想将其拆分并以 html 格式显示为两个单独的列 例如 而不是 Col1 Col2 1 a 2 a 3 a 4 a 5 b 6 b 7 b 8 b

随机推荐

  • 写入器还是输出流?

    我正在设计一个库 其中的类应该能够将自身内部转换为文本 我应该使用哪个类 OutputStream http download oracle com javase 6 docs api java io OutputStream html o
  • 动态地将输入宽度扩展为字符串的长度

    我正在尝试创建一个input至少在宽度上随着用户输入的字符串的长度动态扩展的字段 甚至可能是多行的 这可能吗 input https material angular io components input overviewAngular
  • Excel 中具有层次结构的自动编号

    我想做一个自动汇总编号 我们唯一能做的就是给 A 标题 编号 但字幕应该自动编号 如果标题 1 副标题为 1 1 下方为 1 1 1 依此类推 假设标题 A B 和 C 是副标题 图案应该是这样的 1 A 1 1 B 1 2 B 2 A 2
  • Doctrine 分配错误:无法将 Doctrine\ORM\PersistentCollection 分配给属性

    我有一个上传 我想显示数据库中的所有类别 但我不断收到 EntityType 错误 我不知道为什么之前可以正常工作 这是错误 Cannot assign Doctrine ORM PersistentCollection to proper
  • 如何将子实例反序列化为父对象而不丢失其特定属性?

    下面分几个类 如何序列化 A 实例的 Json 字符串 其中 PropertyB 包含 SpecPropB1 或 SpecPropB2 以便这些属性保留在 C 对象中 public class A public B PropertyB ge
  • 当客户端读取 HashMap 时如何刷新 HashMap

    我有一个静电HashMap在服务器启动时初始化 客户端在登录时从该地图初始化其数据 现在我需要刷新这张地图 但是客户端可以同时登录并从这张地图中获取数据 当他们阅读时 我可以更改如下所示的地图参考吗 我不能使用synchronized因为它
  • jCenter 和 Bintray 正在关闭。怎么办?如果使用第三方库如何解决?

    jCenter 和 Bintray 正在关闭 那么我们该如何解决这个问题 如果项目中使用了第三方库怎么办 请帮帮我 提前致谢 在你所有的build gradle文件替换jcenter by mavenCentral 或者如果 mavenCe
  • 如何在 fxml 项目中使用 font Awesome (javafx)

    我想在我的项目中使用 font Awesome 字体 但我不知道如何在我的项目中使用 font Awesome 我找到了一些示例 但它们不能在 fxml 中使用 很棒的javafx字体 https bitbucket org Jerady
  • 如何根据类的值将类对象添加到 hashMap 中?

    我正在从数据库中检索一些值 这些值需要添加到列表中 然后根据其值添加到具有特定键的 MAP 中 例如 row 1 name A category 1 row 2 name B category 2 row 3 name C category
  • 当我滚动 UIPickerView 时,如何实时获取所选值

    For example in this image when I m scrolling the UIPickerView to 2012 9 28 what I want is that the text of the black lab
  • 如何在 Silverlight 中的 Border 元素上制作虚线边框?

    我怎样才能让这个Border Silverlight元素的底部边框变成红色dotted里面有一个红色的solid line Border border new Border border CornerRadius new CornerRad
  • WPF 图表:如何折叠线系列中的数据点

    我在图表中有多条线系列 首先绘制图表线 然后沿着线绘制点 这很烦人 而且大点的大小使得大型数据集根本毫无用处 目前我正在为每个系列做这个
  • 选择限制功能不适用于reactjs 复选框形式

    我有一个从 json 获取复选框的 React 组件 复选框的每个部分最多可以包含 5 个复选框 我试图将每个部分中的限制设置为最多 2 个选择 但是它没有按应有的方式工作 主要成分是项目列表 js 复选框来自复选框 js 这是我正在尝试做
  • current->mm 在 Linux 内核中给出 NULL

    我想遍历页表 因此我访问了 current gt mm 但它给出了 NULL 值 我正在研究 linux 内核 3 9 我不明白 current gt mm 怎么会为零 这里有什么我想念的吗 这意味着您处于内核线程中 在Linux中 内核线
  • 用MPI发送size_t类型数据

    在 MPI 中发送 size t 类型数字的最安全方法是什么 例如 我确信它是not将其作为 MPI INT 盲目发送是安全的 MPI LONG 总是有效吗 使用宏怎么样 include
  • 选择看起来像错误/缺失功能的重载时,C# 编译器出现奇怪的行为

    我最近发现 C 编译器的一个有趣的行为 想象一下这样的界面 public interface ILogger void Info string operation string details null void Info string o
  • 使用 C 函数扩展 Numpy

    我正在尝试加速我的 Numpy 代码 并决定实现一个特定的函数 而我的代码大部分时间都在 C 中使用 我实际上是 C 的菜鸟 但我设法编写了一个函数 将矩阵中的每一行归一化为 1 我可以编译它 并用一些数据 在 C 中 测试它 它满足了我的
  • 使用 RxJS 将多个 ajax 请求转换为 Observables

    我正在努力解决某件事 我猜这意味着我误解了并且正在做一些愚蠢的事情 我有一个可观察对象 需要使用它来创建一些对象 将其发送到服务器进行处理 将服务器的结果与我发送的对象结合起来 然后将其转换为可观察对象 所以我想要做什么 我认为 就像是 v
  • 具有 http 身份验证的 Zend SOAP 服务器 WSDL URI

    我正在尝试使用 Zend Soap Server 设置 SOAP 服务 ZF1 我的问题是 WSDL URI 受密码保护 可以通过设置 https 用户名 来访问它 电子邮件受保护 cdn cgi l email protection 作为
  • 使 Python 单元测试因任何线程的异常而失败

    我正在使用单元测试框架来自动化多线程 python 代码 外部硬件和嵌入式 C 的集成测试 尽管我公然滥用单元测试框架进行集成测试 但它的效果非常好 除了一个问题 如果任何生成的线程引发异常 我需要测试失败 这可以通过单元测试框架实现吗 一