使用多处理时出现奇怪的unpickling错误

时间:2009-12-23 14:57:48

标签: python exception multiprocessing pickle

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

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并返回字典,则可以正常工作。我做错了什么?

3 个答案:

答案 0 :(得分:3)

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

跟踪问题后,您可以切换回cpickle。

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

答案 1 :(得分:2)

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

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

我使用django-celery(使用多处理模块)遇到了类似的问题。如果我的任务代码产生了本身不可伪装的错误,那么这个多进程/ pickle异常会掩盖信息。因为我还没有想出一个更好的方法来传播错误,所以我会在我的任务代码中调试日志记录来追捕它。我应该更聪明地了解我传递到队列中的内容(防止将异常放到消息队列中,因此多进程模块不会尝试对它们进行pickle / unpickle)。

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

答案 2 :(得分:0)

我已经在C ++,Java和Delphi中完成了线程安全,但是没有使用Python,所以我的评论很简单。

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

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

Another StackOverflow question on python and thread-safety