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

如何捕获subprocess输出?树莓派Discord Bot温度查询及命令执行报错求助

解决Discord Bot执行树莓派命令的问题

让我一步步帮你排查这两段代码的问题,以及怎么正确获取命令输出:

第一段代码的核心问题

你用subprocess.call()来执行命令,但这个函数的返回值是命令的退出状态码(0表示执行成功,非0表示失败),根本不是命令的输出内容。这就是为什么Bot会输出Your RPI3 temp is currently 0——因为vcgencmd measure_temp执行成功,返回了状态码0。

另外补充一点:你写的命令字符串"vcgencmdmeasure_temp"少了空格,正确格式应该是"vcgencmd measure_temp",不过即使命令写对,call()也拿不到输出结果。

第二段代码的报错原因

报错里提到命令'vcgencmdmeasure_temp'返回非零状态码12,这说明系统找不到这个命令。问题出在你处理输入参数的方式:

mesg = ''.join(args)

当你输入vcgencmd measure_temp时,args会被拆成('vcgencmd', 'measure_temp'),用空字符串join之后就变成了没有空格的vcgencmdmeasure_temp,系统自然找不到这个不存在的命令。

另外,subprocess.check_output()如果命令执行失败(退出码非0)会直接抛出CalledProcessError异常,你的代码没有捕获这个异常,所以会触发Discord的CommandInvokeError。

修正方案

1. 修复温度查询命令

用subprocess.check_output()来获取命令输出,同时处理输出内容,还要加异常捕获避免Bot崩溃:

@bot.command(pass_context=True)
async def vcgencmdmeasure_temp(ctx):
    if ctx.message.author.id == "412372079242117123":
        await bot.say("OK....")
        try:
            # 获取命令输出,universal_newlines=True让返回值是字符串而非字节
            temp_result = subprocess.check_output("vcgencmd measure_temp", shell=True, universal_newlines=True)
            # 提取温度值(原始输出格式是'temp=XX.X°C\n')
            temp_value = temp_result.strip().split('=')[1]
            await bot.say(f"Your RPI3 temp is currently: {temp_value}")
        except subprocess.CalledProcessError as e:
            await bot.say(f"Failed to get temperature: {str(e)}")
        except Exception as e:
            await bot.say(f"Unexpected error: {str(e)}")
    else:
        await bot.say("Error user lacks perms(only bot owner can run this)")

2. 修复任意命令执行功能

首先要正确拼接用户输入的命令(用空格join参数),然后捕获异常避免Bot崩溃:

@bot.command(pass_context=True)
async def rpicmd(ctx, *args):
    if ctx.message.author.id == "412372079242117123":
        # 用空格拼接参数,保留命令的正确格式
        cmd = ' '.join(args)
        try:
            # 同时捕获stderr输出,避免错误信息丢失
            command_output = subprocess.check_output(
                cmd, 
                shell=True, 
                universal_newlines=True,
                stderr=subprocess.STDOUT
            )
            await bot.say(command_output)
        except subprocess.CalledProcessError as e:
            await bot.say(f"Command failed with exit code {e.returncode}:\n{e.output}")
        except Exception as e:
            await bot.say(f"Error executing command: {str(e)}")
    else:
        await bot.say("No noob")

或者更优雅的方式,用*, cmd来直接接收完整的命令字符串(不需要手动join):

@bot.command(pass_context=True)
async def rpicmd(ctx, *, cmd):
    if ctx.message.author.id == "412372079242117123":
        try:
            command_output = subprocess.check_output(
                cmd, 
                shell=True, 
                universal_newlines=True,
                stderr=subprocess.STDOUT
            )
            await bot.say(command_output)
        except subprocess.CalledProcessError as e:
            await bot.say(f"Command failed with exit code {e.returncode}:\n{e.output}")
        except Exception as e:
            await bot.say(f"Error executing command: {str(e)}")
    else:
        await bot.say("No noob")

这样用户输入rpicmd vcgencmd measure_temp时,cmd会直接拿到完整的vcgencmd measure_temp字符串,不会出现拼接错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:35:21