Python - 是否有可以序列化到磁盘的线程安全队列?
我在找一个线程安全的队列,能够被序列化或者保存到磁盘上。请问在Python中有没有这样的数据结构?标准的Python队列是不能被序列化的。
2 个回答
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
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
让你可以注册一些辅助函数,用于处理任意对象的序列化和反序列化。简单来说,就是我们可以注册一个新的 Queue
类的版本,然后用这些辅助函数在序列化之前去掉所有不能被序列化的 Lock
和 Condition
实例变量,等到反序列化的时候再把它们加回来。