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

如何在Discord bot中调用外部脚本并将其逐行控制台输出发送到频道

问题解决方法

问题原因

当前使用的subprocess.run()是阻塞式同步调用,存在两个核心问题:

  • 必须等待被调用脚本完全执行结束后才会统一返回所有输出,无法实现实时逐行获取
  • capture_output=True会捕获子进程的所有标准输出/错误流到变量中,自然不会打印到控制台
    同时现有代码存在缩进错误:消息判断逻辑不在on_message回调函数内部,运行时无法触发对应逻辑。

解决方案

改用asyncio异步子进程接口执行脚本,既不会阻塞Discord bot的事件循环,也可以实现逐行实时读取输出,同时兼顾控制台打印和Discord消息发送。

修改后完整代码:

import discord
import asyncio

TOKEN = 'TOKEN(已隐去)'
# 命令映射白名单,避免用户输入恶意路径执行任意脚本,按需配置
CMD_MAP = {
    "script1": "./path/to/script1.py",
    "script2": "./path/to/script2.py"
}

# 注意:discord.py v2.x以上版本需要显式声明intents,同时要在Discord开发者后台开启对应权限
client = discord.Client(intents=discord.Intents.all())

@client.event
async def on_ready():
  print("Logged in as {0.user}".format(client))

@client.event
async def on_message(message):
    username = str(message.author).split("#")[0]
    usermsg = str(message.content)
    channel = str(message.channel.name)
    print(f'{username}, {usermsg}, {channel}')

    if message.author == client.user:
        return

    if message.channel.name == "test" and usermsg.startswith("/"):
        arg = usermsg[1:].strip()
        # 校验命令合法性
        if arg not in CMD_MAP:
            await message.channel.send(f"无效命令,支持的命令:{'、'.join(CMD_MAP.keys())}")
            return
        await message.channel.send(f'Executing your requested script, {username}')
        # 异步启动子进程,-u参数关闭Python输出缓冲,保证输出实时返回
        proc = await asyncio.create_subprocess_exec(
            "python3", "-u", CMD_MAP[arg],
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.STDOUT, # 合并错误流到输出流统一处理
            text=True
        )
        # 逐行读取输出
        while True:
            line = await proc.stdout.readline()
            if not line:
                break
            line = line.strip()
            if not line:
                continue
            # 同时打印到控制台和发送到Discord频道
            print(line)
            await message.channel.send(line)
        # 等待进程完全退出
        await proc.wait()
        await message.channel.send(f"脚本执行结束,退出码:{proc.returncode}")

client.run(TOKEN)

注意事项

  • 若使用discord.py v2.x及以上版本,需要先在Discord开发者后台开启bot的「Message Content Intent」权限,否则无法读取用户消息内容
  • 如果不想给执行命令加-u参数,也可以在被调用脚本的所有print语句中添加flush=True参数,避免输出缓冲导致无法实时获取内容

内容的提问来源于stack exchange,提问作者il_pow23

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 09:15:04