如何在Python中的进程之间传递堆栈跟踪?

2023-12-02

我正在尝试创建一个 python 装饰器,它接受带有 args 和 kwargs 的函数,在新进程中执行它,关闭它并返回函数返回的任何内容,包括引发相同的异常(如果有)。

目前,如果函数没有引发异常,我的装饰器可以正常处理函数,但无法提供回溯。如何将其传回父进程?

from functools import wraps
from multiprocessing import Process, Queue
import sys


def process_wrapper(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        # queue for communicating between parent and child processes
        q = Queue()

        def func_to_q(_q: Queue, *_args, **_kwargs):
            # do the same as func, but put result into the queue. Also put
            # there an exception if any.
            try:
                _res = func(*_args, **_kwargs)
                _q.put(_res)
            except:
                _q.put(sys.exc_info())

        # start another process and wait for it to join
        p = Process(target=func_to_q, args=(q, )+args, kwargs=kwargs)
        p.start()
        p.join()

        # get result from the queue and return it, or raise if it's an exception
        res = q.get(False)
        if isinstance(res, tuple) and isinstance(res[0], Exception):
            raise res[1].with_traceback(res[2])
        else:
            return res
    return wrapper


if __name__ == '__main__':

    @process_wrapper
    def ok():
        return 'ok'

    @process_wrapper
    def trouble():
        def inside():
            raise UserWarning
        inside()

    print(ok())
    print(trouble())

我期望结果是这样的:

ok
Traceback (most recent call last):
  File "/temp.py", line 47, in <module>
    print(trouble())
  File "/temp.py", line 44, in trouble
    inside()
  File "/temp.py", line 43, in inside
    raise UserWarning
UserWarning

Process finished with exit code 1

但子进程似乎无法将堆栈跟踪放入队列中,我得到以下信息:

ok
Traceback (most recent call last):
  File "/temp.py", line 47, in <module>
    print(trouble())
  File "/temp.py", line 26, in wrapper
    res = q.get(False)
  File "/usr/lib/python3.6/multiprocessing/queues.py", line 107, in get
    raise Empty
queue.Empty

Process finished with exit code 1

另外,如果子进程仅将异常本身放入队列_q.put(sys.exc_info()[1]),父级从那里获取它并引发,但使用新的堆栈跟踪(注意缺少对inside()):

ok
Traceback (most recent call last):
  File "/temp.py", line 47, in <module>
    print(trouble())
  File "/temp.py", line 28, in wrapper
    raise res
UserWarning

Process finished with exit code 1

看一眼multiprocessing.pool.py以及用于向父级发送异常的字符串化技巧。您可以使用multiprocessing.pool.ExceptionWithTraceback从那里。

这足以演示基本原理的代码:

from multiprocessing import Process, Queue
from multiprocessing.pool import ExceptionWithTraceback


def worker(outqueue):
    try:
        result = (True, 1 / 0)  # will raise ZeroDivisionError
    except Exception as e:
        e = ExceptionWithTraceback(e, e.__traceback__)
        result = (False, e)
    outqueue.put(result)

if __name__ == '__main__':

    q = Queue()
    p = Process(target=worker, args=(q,))
    p.start()
    success, value = q.get()
    p.join()

    if success:
        print(value)
    else:
        raise value  # raise again

Output:

multiprocessing.pool.RemoteTraceback: 
"""
Traceback (most recent call last):
  File "/home/...", line 7, in worker
    result = (True, 1 / 0)  # will raise ZeroDivisionError
ZeroDivisionError: division by zero
"""

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/...", line 23, in <module>
    raise value
ZeroDivisionError: division by zero

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

如何在Python中的进程之间传递堆栈跟踪? 的相关文章

随机推荐

  • 泛型结构中的运算符重载:我可以为特定类型(?)的泛型创建重载吗?

    我正在 C 中使用通用结构定义物理单位 一切进展顺利 直到出现错误 二元运算符的参数之一必须是包含类型 当尝试重载数学运算符以便它们在不同单位之间进行转换时 所以 我有这样的事情 public interface ScalarUnit pu
  • 如果 Firestore 数据库发生更改,我是否需要重新读取所有文档?

    假设我尝试使用 Firestore 侦听器获取用户喜欢的 eventID 列表 我也使用离线持久化 从这个线程 Firestore 使用缓存直到在线内容更新 我知道侦听器将立即使用缓存中的结果触发 如果有更改结果 我将获得包含更改的另一个快
  • 使用bash对数据进行水平排序

    我有一个充满列数据的文件 sarah mark john 10 20 5 x y z 我想对数据进行排序 使列保持完整 但第二行按递增顺序排列 因此如下所示 john sarah mark 5 10 20 z x y 我一直在查看排序命令
  • 在 OpenCV 中使用 inRange() 检测某个范围内的颜色

    我正在使用 OpenCV 编写一个用于月球陨石坑检测的 C 程序 该程序似乎只能准确检测到一小部分陨石坑 我的这种方法的策略是首先将图像转换为 HSV 然后使用inRange 捕获一系列值中的颜色以产生阈值 然后对其进行高斯模糊并使用Hou
  • Powershell:TabExpansion++ ArgumentCompleter 的多个参数

    我正在开发一个功能来安排用户的主驱动器传输 我将使用 TabExpansion 来允许用户自动完成服务器名称 该名称是从 CSV 文件填充的 两者都会有参数OldServer and NewServer TabExpansion 是否可以为
  • Python 3.6 ModuleNotFoundError:没有名为“pyttsx3”的模块

    我完全不知道会出现什么问题 我执行了 pip 安装程序 pip install pyttsx3 并重新安装了 JetBrains PyCharm 但它仍然无法正常工作 启动 pyCharm 终端窗口 然后安装 pipenv 它是改进的 pi
  • 如何限制用户在 DataGridView 列的特定单元格中仅输入数值?

    我有一个DataGridView我想限制用户在特定列下的单元格中仅输入数值的控件 我怎样才能完成这种类型的验证DataGridView cells 当我创建一个简单的文本框时这是可能的 但是我如何验证DataGridView Cell 您可
  • 无法连接到数据库:用户“@”localhost”对数据库“socialdb”的访问被拒绝

    我见过一些这样的错误 但我没有找到答案 Unable to connect to database Access denied for user localhost to database socialdb Socialdb 是我的数据库
  • 声明一个数组并更改其内容[重复]

    这个问题在这里已经有答案了 我正在编写测试代码来探索数组的属性 为什么这有效 public static void main String args int testing 1 2 3 for int i 0 i
  • 更改 dataGridView 中垂直滚动条的宽度

    我正在开发一个触摸屏应用程序 我被要求增大滚动条的大小 以便用户可以使用它们 到目前为止我还没能解决这个问题 我读到 如果增加 MainForm 窗口滚动条的宽度 则 dataGridView 将继承它 我尝试了一些方法 但到目前为止还没有
  • 在流星方法中使用集合插入中的 id

    在我的 Angular Meteor 应用程序中 我想使用从插入到客户端的 Meteor 方法中的集合创建的 id 在客户端 Angular 组件中存在以下方法 onSubmit void Meteor call insertItem th
  • 有没有办法从 JS 中的图像手动创建 Base64code

    我在 html 画布上绘制图像 这就是计算像素的方法 for var i 0 i lt data length i 4 var red data i red var green data i 1 green var blue data i
  • 如何使用 OGNL 索引引用运算符

    使用 OGNL 您可以引用操作上下文对象 例如 application session root action request parameters attr 以及动作上下文 context 该框架将 OGNL 上下文设置为我们的 Acti
  • NodeJS HTML 和 CSS

    我不知道为什么 CSS 在这里被忽略 为了能够在 HTML 中使用 CSS 我需要对 NodeJS 做一些特定的事情吗 它与标签的 type 属性有什么关系吗 NodeJS 代码 app get function request respo
  • 在 IntelliJ 中可以实现而在 Eclipse 中无法实现的事情?

    Locked 这个问题及其答案是locked因为这个问题是题外话 但却具有历史意义 目前不接受新的答案或互动 我听说有人改变了其中一种方式 并且对其中一种发誓 作为 Eclipse 的忠实粉丝 但还没有时间尝试 IntelliJ 我有兴趣从
  • printf,如何为整数插入小数点

    我有一个UINT16说的无符号整数 4455 312 560 or 70 如何使用 printf 在最后两位数字之前插入小数点 以便示例数字显示为 44 55 3 12 5 60 or 0 70 如果没有 printf 解决方案 是否有其他
  • 如何在下拉淘汰赛js中预先选择一个选项

    我已经查看了其他问题 但无法让我的选择框正常工作 绑定下拉 选择 列表的初始 默认值 我有以下游戏对象 function Game visitingTeamDetails homeTeamDetails game if arguments
  • 如何在android中绘制球体

    如何使用 OpenGL ES 在 Android 中绘制球体 您的问题可能与以下问题重复 在OPENGL ES中绘制球体时出现问题 在 OpenGL ES 中绘制球体 我建议您在提出问题之前先做一些研究 因为有很多教程可用于相同的内容 ht
  • 有没有办法禁用 Swing 应用程序的 Mac OS Retina 缩放?

    我们有一个相当复杂的应用程序 需要尽可能多的屏幕空间 自然 视网膜显示屏 Mac Book 非常适合此目的 然而 在 Swing 中这些设备似乎使用的是点而不是像素 它们允许我将图标更改为所讨论的更高分辨率版本here 但由于我们做了很多复
  • 如何在Python中的进程之间传递堆栈跟踪?

    我正在尝试创建一个 python 装饰器 它接受带有 args 和 kwargs 的函数 在新进程中执行它 关闭它并返回函数返回的任何内容 包括引发相同的异常 如果有 目前 如果函数没有引发异常 我的装饰器可以正常处理函数 但无法提供回溯