我正在使用一个可以被pickle或序列化为磁盘的线程安全队列。 python中是否有任何数据结构可以执行此操作。标准的python Queue无法被腌制。
答案 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)
dill
和cloudpickle
等模块已经知道如何序列化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
,问题就解决了。
在此处获取dill
:https://github.com/uqfoundation