Python - 是否有一个可以被pickle或以其他方式序列化到磁盘的线程安全队列?

时间:2014-08-20 02:36:58

标签: python multithreading serialization queue pickle

我正在使用一个可以被pickle或序列化为磁盘的线程安全队列。 python中是否有任何数据结构可以执行此操作。标准的python Queue无法被腌制。

2 个答案:

答案 0 :(得分:3)

这可以使用copy_reg模块完成,但这不是世界上最优雅的事情:

import copy_reg
import threading
import pickle
from Queue import Queue as _Queue

# Make Queue a new-style class, so it can be used with copy_reg
class Queue(_Queue, object):
    pass

def pickle_queue(q):
    # Shallow copy of __dict__ (the underlying deque isn't actually copied, so this is fast)
    q_dct = q.__dict__.copy()
    # Remove all non-picklable synchronization primitives
    del q_dct['mutex']
    del q_dct['not_empty']
    del q_dct['not_full']
    del q_dct['all_tasks_done']
    return Queue, (), q_dct

def unpickle_queue(state):
    # Recreate our queue.
    q = state[0]()
    q.mutex = threading.Lock()
    q.not_empty = threading.Condition(q.mutex)
    q.not_full = threading.Condition(q.mutex)
    q.all_tasks_done = threading.Condition(q.mutex)
    q.__dict__ = state[2]
    return q

copy_reg.pickle(Queue, pickle_queue, unpickle_queue)

q = Queue()
q.put("hey")
d = pickle.dumps(q)

new_q = pickle.loads(d)
print new_q.get()
# Outputs 'hey'

copy_reg允许您注册辅助函数或者对任意对象进行pickle和unpickling。因此,我们注册Queue类的新样式版本,并使用辅助函数在pickle之前删除所有不可用的Lock / Condition实例变量,并在之后添加它们在unpickle。

答案 1 :(得分:1)

dillcloudpickle等模块已经知道如何序列化Queue。 他们已经为您完成了copy_reg

>>> from Queue import Queue
>>> q = Queue()
>>> q.put('hey')
>>> import dill as pickle
>>> d = pickle.dumps(q)
>>> _q = pickle.loads(d)
>>> print _q.get()
hey
>>> 

就这么简单!只需import dill as pickle,问题就解决了。

在此处获取dillhttps://github.com/uqfoundation