You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 09:43:36