Python 多处理进程无声地崩溃

2024-02-04

我正在使用Python 2.7.3。我使用子类化了一些代码multiprocessing.Process对象。如果我的子类 Process 对象中的代码没有错误,则一切运行正常。但是,如果我的子类 Process 对象中的代码存在错误,它们显然会默默地崩溃(没有堆栈跟踪打印到父 shell),并且 CPU 使用率将降至零。父代码永远不会崩溃,给人的印象是执行只是挂起。同时,很难追踪代码中的错误在哪里,因为没有给出错误在哪里的指示。

我在 stackoverflow 上找不到处理相同问题的任何其他问题。

我猜子类化的 Process 对象似乎会无声地崩溃,因为它们无法将错误消息打印到父级的 shell,但我想知道我可以对此做些什么,以便我至少可以更有效地调试(并且其他我的代码的用户也可以在遇到问题时告诉我)。

EDIT:我的实际代码太复杂了,但是一个带有错误的子类化 Process 对象的简单示例将如下所示:

from multiprocessing import Process, Queue

class Worker(Process):

    def __init__(self, inputQueue, outputQueue):

        super(Worker, self).__init__()

        self.inputQueue = inputQueue
        self.outputQueue = outputQueue

    def run(self):

        for i in iter(self.inputQueue.get, 'STOP'):

            # (code that does stuff)

            1 / 0 # Dumb error

            # (more code that does stuff)

            self.outputQueue.put(result)

您真正想要的是某种将异常传递给父进程的方法,对吧?然后你就可以随心所欲地处理它们了。

如果你使用concurrent.futures.ProcessPoolExecutor http://docs.python.org/dev/library/concurrent.futures.html,这是自动的。如果你使用multiprocessing.Pool http://docs.python.org/dev/library/multiprocessing.html#using-a-pool-of-workers,这是微不足道的。如果您使用显式Process and Queue,你必须做一些工作,但这不是that much.

例如:

def run(self):
    try:
        for i in iter(self.inputQueue.get, 'STOP'):
            # (code that does stuff)
            1 / 0 # Dumb error
            # (more code that does stuff)
            self.outputQueue.put(result)
    except Exception as e:
        self.outputQueue.put(e)

然后,你的调用代码就可以读取Exception像其他任何事情一样从队列中消失。而不是这个:

yield outq.pop()

do this:

result = outq.pop()
if isinstance(result, Exception):
    raise result
yield result

(我不知道你的实际父进程队列读取代码是做什么的,因为你的最小样本只是忽略了队列。但希望这可以解释这个想法,即使你的真实代码实际上并不是这样工作的。)

这假设您想要中止任何未处理的异常,使其达到run。如果你想传回异常并继续下一步i in iter,只需移动try进入for,而不是围绕它。

这还假设Exceptions 不是有效值。如果这是一个问题,最简单的解决方案就是推动(result, exception) tuples:

def run(self):
    try:
        for i in iter(self.inputQueue.get, 'STOP'):
            # (code that does stuff)
            1 / 0 # Dumb error
            # (more code that does stuff)
            self.outputQueue.put((result, None))
    except Exception as e:
        self.outputQueue.put((None, e))

然后,您的弹出代码将执行以下操作:

result, exception = outq.pop()
if exception:
    raise exception
yield result

您可能会注意到,这类似于 node.js 回调样式,您可以在其中传递(err, result)每个回调。是的,这很烦人,而且你会弄乱这种风格的代码。但除了包装器之外,您实际上并没有在任何地方使用它;所有从队列中获取值或在内部调用的“应用程序级”代码run只看到正常的回报/收益率和引发的异常。

您甚至可能想考虑建立一个Future至规格concurrent.futures(或按原样使用该类),即使您正在手动排队和执行工作。这并不难,而且它为您提供了一个非常好的 API,特别是对于调试而言。

最后,值得注意的是,大多数围绕工作线程和队列构建的代码都可以通过执行器/池设计变得更加简单,即使您绝对确定每个队列只需要一个工作线程。只需废弃所有样板,然后转动循环即可Worker.run方法到函数中(这只是returns or raises 正常,而不是附加到队列)。在调用方,再次废弃所有样板文件,然后submit or map工作功能及其参数。

您的整个示例可以简化为:

def job(i):
    # (code that does stuff)
    1 / 0 # Dumb error
    # (more code that does stuff)
    return result

with concurrent.futures.ProcessPoolExecutor(max_workers=1) as executor:
    results = executor.map(job, range(10))

并且它会自动正确处理异常。


正如您在评论中提到的,异常的回溯不会回溯到子进程;而是回溯到子进程。它只限于手册raise result调用(或者,如果您使用的是池或执行器,则调用池或执行器的内部)。

原因是multiprocessing.Queue是建立在pickle,并且腌制异常不会腌制它们的回溯。原因是你无法腌制回溯。原因是回溯充满了对本地执行上下文的引用,因此让它们在另一个进程中工作将非常困难。

那么……你能对此做些什么呢?不要去寻找完全通用的解决方案。相反,想想你真正需要什么。 90% 的情况下,您想要的是“记录异常,带回溯,然后继续”或“打印异常,带回溯,以stderr and exit(1)就像默认的未处理异常处理程序一样。对于其中任何一个,您根本不需要传递异常;只需在子端格式化它并传递一个字符串即可。如果您do需要更奇特的东西,准确地计算出您需要的东西,并传递足够的信息来手动将它们组合在一起。如果您不知道如何格式化回溯和异常,请参阅traceback http://docs.python.org/2/library/traceback.html模块。这很简单。这意味着您根本不需要进入泡菜机器。 (并不是说很难copyreg一个 pickler 或编写一个持有者类__reduce__方法或任何东西,但如果你不需要,为什么要学习所有这些?)

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

Python 多处理进程无声地崩溃 的相关文章

随机推荐

  • 前向声明类成员的前向声明

    是否可以前向声明一个在另一个前向声明的类中声明的类 基本上 我有这样的东西 A h class A struct B 现在我想声明另一个这样的类 Q h class A struct A B class Q A B Foo 不 这是不可能的
  • 在 WordPress 中获取类别 ID 数组?

    cats get categories array order gt ASC orderby gt id hierarchical gt 0 hide empty gt 0 taxonomy gt edu year 我想生成一个变量 其中包
  • 当作为 *.a 静态库链接时,为什么“WinMain”无法解析?

    给定一个简单的程序 include
  • 如何将 PHPUnit 与 CodeIgniter 结合使用?

    我读过并阅读过有关 PHPUnit SimpleTest 和其他单元测试框架的文章 他们听起来都很棒 我终于让 PHPUnit 与 Codeigniter 一起工作了 感谢https bitbucket org kenjis my ciun
  • 默认模板参数在部分特化上下文中的作用

    我不清楚部分专业化背景下默认模板参数的交互 以选择哪个是更好的匹配模板 这个问题源于此中发布的代码answer https stackoverflow com questions 52565407 use of enable if to m
  • Jenkins Slave 问题 - 无效的流标头:099EACED

    Jenkins 2 7 4 安装在 RedHat 服务器中 并且通过选择 通过在主服务器上执行命令来启动代理 选项来配置 Linux 从站 我们创建了一个 Shell 脚本 它在 Jenkins 版本 2 7 4 中运行良好 现在我们将 J
  • “这个”阴影是个好主意吗?

    隐藏类变量的情况在 Java 中很常见 Eclipse 将愉快地生成以下代码 public class TestClass private int value private String test public TestClass int
  • 将数据库设置从 application.ini 中取出并放入环境中

    在基于 Zend 的应用程序的传统编码中 数据库设置存储在 application ini 中 这会存储每个应用程序的设置 StackOverflow 上是否有人探索过将数据库设置从 application ini 移动到环境中的可能性 例
  • Picasso 库无法在 Android 上从 SD 卡加载图像

    我从图像库的路径中获取一个文件 并尝试将其加载到图像视图 如下所示 文件路径为 storage sdcard0 DCIM Camera 1436267579864 jpg 我也尝试传递 Uri 我也有 SD 卡的读取权限 它最终在onErr
  • 如何通过IP获取时区[重复]

    这个问题在这里已经有答案了 我有一个注册 通过它我可以获得注册用户的IP地址 我想通过用户的 IP 地址获取用户的时区 就像在 jquery 中我们可以得到这样的结果jquery 中的时区 http pellepim bitbucket o
  • 如何获取 .NET 中的资源监视器值?

    我需要获取 Windows 7 资源监视器中的一些值 特别是每个进程的内存使用情况 CPU 和带宽 我研究了 PerformanceCounter 类 但没有找到深入到进程级别的方法 资源监视器正是我正在寻找的东西 在你问之前 我知道这是重
  • raise StopIteration 和生成器中的 return 语句有什么区别?

    我很好奇使用之间的区别raise StopIteration and a return生成器中的语句 例如 这两个函数有什么区别吗 def my generator0 n for i in range n yield i if i gt 5
  • 安装 pydev 时出错[重复]

    这个问题在这里已经有答案了 我安装了 eclipse 3 7 并且想从 help gt install new software 从 pydev org updates 安装 pydev 但我不断收到错误 An error occurred
  • Python描述符与属性[重复]

    这个问题在这里已经有答案了 我对何时使用属性和描述符感到困惑 我读到属性是一个专门的描述符 有人可以发布这是如何工作的吗 您应该阅读有关描述符实际是什么的文档 Cliff s Notes 版本 描述符是一种低级机制 可让您挂钩正在访问的对象
  • Rails 5 资产未在生产中加载

    我最近更新了 Rails 应用程序中的一些软件包 但现在我的资产无法提供服务 相反 我收到以下错误 Failed to load resource the server responded with a status of 404 Not
  • 制作 VB-dll 并将其加载到 C++ 应用程序中

    我有一个问题已经困扰了整整一周 但我自己无法解决 我一直在谷歌搜索 并在各种论坛中搜索 我发现了很多 这可能有用 尝试过 但没有 没有成功 如果有人有任何线索 请帮助我 我从外部源获得了许多用 VB 编写的类和函数 我需要能够在 C 应用程
  • 从文件中读取特殊字符 - Java

    我正在从具有以下属性的文本文件中读取数据 编码 ANSI文件类型 电脑 现在 该文件包含许多特殊字符 例如度数符号 等 我正在使用以下代码读取该文件 File file new File C X Y SpecialCharacter txt
  • OpenCV VideoCapture 从视频中删除 Alpha 通道

    我有带有 Alpha 通道的视频 我尝试将其放置在另一个视频上 如下所示 public static void overlayImage Mat background Mat foreground Mat output Point loca
  • Javascript Date 对象返回 1969 年 12 月 31 日

    If you are using a date in the form of milliseconds does it need to be converted to a string in order for the Date objec
  • Python 多处理进程无声地崩溃

    我正在使用Python 2 7 3 我使用子类化了一些代码multiprocessing Process对象 如果我的子类 Process 对象中的代码没有错误 则一切运行正常 但是 如果我的子类 Process 对象中的代码存在错误 它们