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

Pycord机器人:如何在调用者上下文运行多行Python脚本?

解决方案

一、用附件参数替代字符串参数解决多行输入问题

直接在斜杠命令里添加Attachment类型的参数,读取上传的文本文件内容作为脚本输入,同时做基础的文件格式校验:

import discord
from discord.ext import commands

bot = commands.Bot(command_prefix="!", intents=discord.Intents.all())

@bot.slash_command(name="dev", description="仅所有者可用的调试执行命令")
@commands.is_owner()
async def dev(ctx, script_file: discord.Attachment):
    # 只允许上传文本类文件
    if not script_file.filename.endswith((".txt", ".py")):
        await ctx.respond("只能上传 .txt 或 .py 格式的文本文件")
        return
    
    # 读取文件内容
    try:
        script_content = await script_file.read()
        script_content = script_content.decode("utf-8")
    except Exception as e:
        await ctx.respond(f"读取文件失败: {str(e)}")
        return
    
    # 调用执行脚本的逻辑
    await run_script(ctx, script_content)

二、用exec执行多行脚本并捕获输出

eval只能处理单个表达式,多行脚本改用exec,同时通过重定向标准输出捕获print内容,还可以注入机器人上下文变量方便调试:

import io
import sys
from contextlib import redirect_stdout
import ast

async def run_script(ctx, script):
    # 注入常用变量到执行环境,方便调试时直接用
    local_env = {
        "bot": ctx.bot,
        "ctx": ctx,
        "discord": discord,
        "commands": commands
    }

    output_buf = io.StringIO()
    result = None
    error_msg = None

    try:
        # 重定向stdout捕获print输出
        with redirect_stdout(output_buf):
            exec(script, globals(), local_env)
        
        # 额外处理:如果脚本最后一行是表达式,获取其返回值
        tree = ast.parse(script)
        if tree.body and isinstance(tree.body[-1], ast.Expr):
            last_expr = ast.unparse(tree.body[-1])
            result = eval(last_expr, globals(), local_env)
    except Exception as e:
        error_msg = str(e)
    
    # 整理响应内容
    response_parts = []
    if output := output_buf.getvalue():
        response_parts.append(f"输出内容:\n```\n{output}\n```")
    if result is not None:
        response_parts.append(f"返回结果:\n```\n{result}\n```")
    if error_msg:
        response_parts.append(f"执行错误:\n```\n{error_msg}\n```")
    
    if not response_parts:
        response_parts.append("脚本执行完成,无输出或返回值")
    
    # 发送响应(如果内容过长可以拆分或转成文件发送)
    await ctx.respond("\n".join(response_parts))

额外注意事项

  • 务必严格限制命令权限,除了@commands.is_owner(),也可以直接硬编码你的用户ID做双重校验,避免权限泄露
  • 执行用户上传的脚本存在极高安全风险,仅在你完全可控的机器人环境中使用
  • 如果脚本执行时间过长,会触发Discord的命令超时,可考虑用异步任务包装并设置超时时间

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 03:40:13