Discord机器人多进程下字典数据同步异常问题求助
问题:Discord机器人多进程中字典无法跨进程更新读取
我正在开发Discord机器人,遇到如下问题:在on_message()函数中修改字典mps的内容后,loop()函数始终无法读取到更新后的字典数据,仅输出空字典。以下是相关代码片段:
import discord import multiprocessing import time client = discord.Client(intents=discord.Intents.all()) mps = {} max_mps = 10 @client.event async def on_message(message): if message.author != client.get_user(BOT_ID): user_id = str(message.author.id) if user_id in mps: mps.update({user_id : mps[user_id] + 1}) #mps[user_id] += 1 #print(mps[user_id]) else: mps.update({user_id : 1}) #mps[user_id] = 1 #print(mps[user_id]) #print(len(mps),"by message") print(mps) def loop(): while True: print("Current mps:", mps) print(len(mps),"by while") if len(mps): print("true") for id,mpss in mps.items(): print(id,mpss) if mpss > 0: mpss -= 1 print(mpss) time.sleep(1) d = multiprocessing.Process(target=detect) l = multiprocessing.Process(target=loop) if __name__ == "__main__": d.start() l.start() client.run("TOKEN")
原因分析
multiprocessing创建的每个进程都拥有独立的内存空间,你定义的全局字典mps会被每个进程复制一份。on_message所在的Discord客户端进程修改的是自己的字典副本,而loop进程读取的是它自己的副本,两者数据完全隔离,因此出现无法同步的问题。
解决方法
方法1:使用multiprocessing.Manager创建可共享字典
Manager会启动一个独立的服务器进程,让所有子进程通过代理访问共享数据,实现跨进程的数据同步。修改后的代码如下:
import discord import multiprocessing import time client = discord.Client(intents=discord.Intents.all()) # 用Manager创建跨进程共享的字典 manager = multiprocessing.Manager() mps = manager.dict() max_mps = 10 BOT_ID = 你的机器人ID # 替换为实际机器人ID TOKEN = "你的机器人令牌" # 替换为实际令牌 @client.event async def on_message(message): if message.author != client.get_user(BOT_ID): user_id = str(message.author.id) if user_id in mps: mps[user_id] += 1 else: mps[user_id] = 1 print(f"on_message中mps: {dict(mps)}") def loop(): while True: current_mps = dict(mps) print("Current mps:", current_mps) print(len(current_mps),"by while") if len(current_mps): print("true") # 遍历前转成普通字典副本,避免迭代时修改共享字典引发异常 for id, mpss in current_mps.items(): print(id, mpss) if mpss > 0: mps[id] = mpss - 1 print(mps[id]) time.sleep(1) # 原代码中detect函数未定义,此处注释或补充定义 # d = multiprocessing.Process(target=detect) l = multiprocessing.Process(target=loop) if __name__ == "__main__": # d.start() l.start() client.run(TOKEN) # d.join() l.join()
关键修改点
- 用
manager.dict()替代普通字典,创建跨进程共享的字典实例 - 遍历共享字典时先转成普通字典副本,避免迭代过程中修改数据引发异常
- 修改字典值时直接操作共享字典,确保所有进程读取到的是同一数据
方法2:改用线程替代进程
如果不需要真正的并行计算,只是需要后台循环任务,使用线程更简单——线程共享同一内存空间,无需额外同步机制:
import discord import threading import time client = discord.Client(intents=discord.Intents.all()) mps = {} max_mps = 10 BOT_ID = 你的机器人ID TOKEN = "你的机器人令牌" @client.event async def on_message(message): if message.author != client.get_user(BOT_ID): user_id = str(message.author.id) if user_id in mps: mps[user_id] += 1 else: mps[user_id] = 1 print(f"on_message中mps: {mps}") def loop(): while True: print("Current mps:", mps) print(len(mps),"by while") if len(mps): print("true") for id, mpss in mps.items(): print(id, mpss) if mpss > 0: mps[id] -= 1 print(mps[id]) time.sleep(1) if __name__ == "__main__": # 创建守护线程,主进程退出时自动结束 l = threading.Thread(target=loop, daemon=True) l.start() client.run(TOKEN)
内容的提问来源于stack exchange,提问作者tvixter
相关产品推荐
相关产品推荐

