多进程 报错 TypeError: cannot pickle ‘_thread.lock‘ object

文章描述了一个在运行Flaskweb应用同时尝试使用WebSocket时遇到的问题,由于不能同时运行线程和协程,作者选择使用多进程,但遇到了TypeError关于无法序列化_thread.lock对象的错误。解决方案是将传递给子进程的对象属性改为可序列化的,比如将redis对象改为redis配置,然后在子进程中创建redis对象。经过修改,Flask和WebSocket都能正常运行。
摘要由CSDN通过智能技术生成

问题

在运行flask web时候也需要运行websocket
调试websocket对象用协程,线程都无法两者都运行,因此使用多线程,多线程也有报错 TypeError: cannot pickle ‘_thread.lock’ object

代码:

class ws_utils(object):
    def __init__(self, ws_config, redis):
        self.host = ws_config['ip']
        self.port = ws_config['port']
        self.redis = redis
        self.cache = {}

if __name__ == '__main__':
	global redis
    redis = Redis(config['redis'])
    global database
    database = Database(config['manager-server'])
    # 2.register nacos
    nacos_register()
    # 3.ws task: new process
    ws = ws_utils(config['ws'], redis)
    p = Process(target=ws.runWS)
    p.start()
    server = config['server']
    app.run(host=server["ip"], port=server["port"])

在多进程执行报错

Traceback (most recent call last):
  File "C:\Users\miaochangbin\PycharmProjects\eduCrawler\main.py", line 138, in <module>
    p.start()
  File "D:\Program Files\python\lib\multiprocessing\process.py", line 121, in start
    self._popen = self._Popen(self)
  File "D:\Program Files\python\lib\multiprocessing\context.py", line 224, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
  File "D:\Program Files\python\lib\multiprocessing\context.py", line 327, in _Popen
    return Popen(process_obj)
  File "D:\Program Files\python\lib\multiprocessing\popen_spawn_win32.py", line 93, in __init__
    reduction.dump(process_obj, to_child)
  File "D:\Program Files\python\lib\multiprocessing\reduction.py", line 60, in dump
    ForkingPickler(file, protocol).dump(obj)
TypeError: cannot pickle '_thread.lock' object
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "D:\Program Files\python\lib\multiprocessing\spawn.py", line 116, in spawn_main
    exitcode = _main(fd, parent_sentinel)
  File "D:\Program Files\python\lib\multiprocessing\spawn.py", line 126, in _main
    self = reduction.pickle.load(from_parent)
EOFError: Ran out of input

原因

根据晚上查找资料说是在开启进程,会将信息序列化后传递到子进程,报错就是在信息进行序列化时候。
这边信息报错传递子进程的对象信息(属性以及属性的属性)。
猜测是上面ws_utils对象进行序列化问题,比较容易猜测,redis对象序列化存在问题。
验证下(将redis对象改成None类型):

  ws = ws_utils(config['ws'], redis)

改成

   ws = ws_utils(config['ws'], None)

再次运行后,执行正常
在这里插入图片描述

解决

知道上面原因就好解决
将对象的属性改成可序列化即可
可以在ws_utils对象中创建全局变量redis,而不直接传redis对象,而传redis配置(或者直接从配置文件读取)部分

import asyncio
import websockets
from threading import Thread
from common.utils.redisUtils import Redis


class ws_utils(object):
	# 1.修改参数 redis -> redis_config
    def __init__(self, ws_config, redis_config):
        self.host = ws_config['ip']
        self.port = ws_config['port']
        self.redis_config = redis_config
        self.cache = {}

    def runWS(self):
    	# 2.多进程方法中创建redis对象全局变量
        global redis
        redis = Redis(self.redis_config)
        
if __name__ == '__main__':
	global redis
    redis = Redis(config['redis'])
    global database
    database = Database(config['manager-server'])
    # register nacos
    nacos_register()
    # ws task: new process
    # 3.参数 redis配置
    ws = ws_utils(config['ws'], config['redis'])
    p = Process(target=ws.runWS)
    p.start()
    server = config['server']
    app.run(host=server["ip"], port=server["port"])

运行规后达到效果,flask能运行,ws也能访问
在这里插入图片描述

参考

https://blog.csdn.net/LutingWang/article/details/124203032

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tobin liao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值