【问题标题】:Weird unpickling error when using multiprocessing使用多处理时出现奇怪的解酸错误
【发布时间】:2010-12-29 12:33:59
【问题描述】:

使用多处理时出现以下错误:

Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python2.6/threading.py", line 525, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.6/threading.py", line 477, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/usr/lib/python2.6/multiprocessing/pool.py", line 282, in _handle_results
    task = get()
UnpicklingError: NEWOBJ class argument has NULL tp_new

我完全不知道这意味着什么,尽管这听起来像是 C 级别的问题。任何人都可以对此有所了解吗?

更新:好的,所以我想出了如何解决这个问题。但我还是有点困惑。我正在返回这个类的一个实例:

class SpecData(object):
    def __init__(self, **kwargs):
        self.__dict__.update(**kwargs)
    def to_dict(self):
        return self.__dict__

如果我返回这个对象的一个​​实例,我会得到错误。但是,如果我调用 to_dict 并返回字典,它就可以工作。我做错了什么?

【问题讨论】:

    标签: python exception multiprocessing pickle python-multiprocessing


    【解决方案1】:

    尝试使用pickle 模块而不是cPickle 模块——pickle 是用纯 Python 编写的,而且它通常提供比cPickle 更有用的错误消息。 (虽然有时我不得不求助于制作pickle.py 的本地副本,并在错误位置附近添加一些调试 printf 语句以找出问题。)

    一旦找到问题,就可以切换回 cpickle。

    (我对多处理模块不太熟悉,所以我不确定你是在做酸洗还是它。如果是,那么让它使用 pickle 而不是 cpickle 的最简单方法可能在导入多处理/线程模块之前做一些猴子补丁:import sys, pickle; sys.modules['cPickle']=pickle)

    【讨论】:

      【解决方案2】:

      我认为这是一些 python 函数的可拾取性/不可拾取性的问题。看这篇文章:

      http://khinsen.wordpress.com/2012/02/06/teaching-parallel-computing-in-python/

      我在使用 django-celery(它使用多处理模块)时遇到过类似的问题。如果我的任务代码抛出本身不可挑选的错误,则此多进程/pickle 异常会掩盖信息。因为我还没有找到更好的方法来传播错误,所以我求助于在我的任务代码中调试日志记录来寻找它。我可能应该更聪明地了解我传递到队列的内容(防止将异常放入消息队列,因此多进程模块不会尝试腌制/取消腌制它们)。

      在上述情况下,您可能需要确保 SpecData.__dict__ 是可腌制的。见http://docs.python.org/library/pickle.html#pickle-protocol

      【讨论】:

        【解决方案3】:

        我在 C++、Java 和 Delphi 中完成了线程安全,但没有在 Python 中完成,所以请对我的 cmets 持保留态度。

        This page on Python and Thread-Safety 特别提到了将字典分配为原子和线程安全的。也许您对自定义类的引用不是线程安全的?如果您仍希望在两个线程之间传递自定义容器类,请尝试添加一些推荐的锁定机制。

        我发现其他搜索结果强调 Python 是完全线程安全的,这很有趣。 The Python docs themself 声明提供了锁和其他机制来帮助线程化应用程序,所以看起来这是互联网错误的情况(甚至会发生这种情况吗??)。

        Another StackOverflow question on python and thread-safety.

        【讨论】:

        • 我实际上并没有使用线程。多处理模块通过启动单独的进程来工作。然后,进程通过序列化对象并通过队列传递它们进行通信。反序列化该对象时出现错误。
        • @Kieveli,关于 Python 是“完全线程安全的”,关键是对虚拟机完成的原语和其他内部操作的访问是安全的。由于多线程访问,诸如字典之类的东西不能进入无效状态、使机器崩溃等。这与说您的应用程序不受线程同步问题的影响完全不同。在设计不佳的应用程序中总是可能出现竞争条件和死锁,需要以通常的方式解决。一些工具(例如队列模块)即使在应用程序级别也有很大帮助。
        猜你喜欢
        • 2018-07-26
        • 2012-05-11
        • 2015-05-05
        • 2015-12-07
        • 2014-03-14
        • 2016-02-05
        • 1970-01-01
        • 2017-03-30
        • 2020-08-30
        相关资源
        最近更新 更多