Python - 是否有可以序列化到磁盘的线程安全队列?

1 投票
2 回答
2595 浏览
提问于 2025-04-18 17:52

我在找一个线程安全的队列,能够被序列化或者保存到磁盘上。请问在Python中有没有这样的数据结构?标准的Python队列是不能被序列化的。

2 个回答

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

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 类的版本,然后用这些辅助函数在序列化之前去掉所有不能被序列化的 LockCondition 实例变量,等到反序列化的时候再把它们加回来。

撰写回答