【问题标题】:Unable to pickle redis-py instance (_thread.lock)无法腌制 redis-py 实例 (_thread.lock)
【发布时间】:2018-09-12 13:20:55
【问题描述】:

我正在使用来自(事实上的标准)的 Redis 客户端 python 实现:https://pypi.org/project/redis/

所以我在后台定义了多个worker,每个worker都有一个在启动时创建的连接实例:

class Worker(Process):
    _db = None

    def __init__(self):
        super(Worker, self).__init__()
        self._db = redis.Redis(host="1.2.3.4", port=1234, db=0)

但是,每当我尝试启动此工作器的实例时,都会收到以下错误消息:

TypeError: can't pickle _thread.lock objects

所以我猜这个实现在某处使用了锁。此问题的解决方法是什么?

【问题讨论】:

    标签: python python-3.x redis multiprocessing python-multiprocessing


    【解决方案1】:

    在具有分叉的 Unix-y 操作系统上,您不会遇到此问题,但对于 Windows 而言,它似乎是一种廉价的解决方法,即延迟 redis 实例化,直到在新进程中调用 run

    from multiprocessing import Process
    import redis
    
    class Worker(Process):
        _db = None
        def __init__(self):
            super().__init__()
            self._db = None
        def run(self):
            self._db = redis.Redis(host='localhost', port=6379, db=0)
            # do stuff
    
    if __name__ == '__main__':
        w = Worker()
        w.start()
        w.join()
    

    【讨论】:

    • 我昨天遇到了这个解决方案,但我找不到解释为什么它会在 WinOS 上发生?
    • @Kristijan 它发生在 Windows 上,因为 Windows 不支持进程创建的分叉,只支持生成。因此,您的 redis 实例需要被腌制,并且失败,因为它包含一个线程锁并且这些不能被腌制。
    • 是的——但为什么它在 run 方法中起作用而不在构造函数中起作用?这是一个正在创建的新对象,它没有作为参数从父级传递,以便对其进行腌制?
    • @Kristijan run 在新创建的进程中被调用,而不是在父进程中。
    • 啊,现在说得通了 :) 所以 redis 连接是在父进程中初始化的。我认为 init 正在孩子中被调用。谢谢!
    猜你喜欢
    • 2017-10-23
    • 1970-01-01
    • 2017-12-18
    • 2021-05-30
    • 2021-05-16
    • 2019-05-11
    • 2017-12-04
    • 1970-01-01
    • 2019-02-19
    相关资源
    最近更新 更多