Python新手开发Discord Bot遇编译错误,请求排查脚本交互缺陷
核心问题梳理
你的代码存在多处逻辑错误和不规范写法,导致功能无法正常运行,甚至会破坏原脚本文件。以下是具体问题和修复方案:
Bot代码的明显错误与缺陷
错误的字符串替换逻辑
你设置的STRING_TO_REPLACE = "addresses"会直接把查询脚本中的变量名addresses替换成用户输入的钱包地址,导致脚本变成类似["0x123..."] = ["WALLET_ADDRESS"]的非法代码,完全无法运行。正确做法是替换查询脚本中的WALLET_ADDRESS占位符,而非变量名。永久修改原脚本文件
每次运行命令都会直接覆盖查询脚本内容,多次执行后原脚本会彻底混乱。正确方式是通过命令行参数传递钱包地址给查询脚本,而非修改文件内容。未处理命令参数缺失的情况
如果用户只输入!run_script而没有跟上钱包地址,message.content.split()[1]会抛出索引越界异常,导致Bot崩溃。未处理脚本运行异常
subprocess.check_output会在脚本返回非零退出码时抛出异常,未捕获的话会导致Bot崩溃。同时,查询脚本中的input('Press ENTER to exit')会导致subprocess调用时卡住,因为没有交互输入通道。无用的阻塞代码
client.run(BOT_TOKEN)是阻塞调用,Bot运行后后面的input('Press ENTER to exit')永远不会执行,可直接删除。
查询脚本的问题
硬编码占位符且无参数接收逻辑
脚本只能使用固定的WALLET_ADDRESS,无法通过外部参数接收地址,导致必须修改文件才能更换地址。网络请求未处理异常
requests.get没有处理超时、连接失败、HTTP错误码等情况,一旦请求失败会直接抛出异常终止脚本。脆弱的JSON解析逻辑
使用list(a1['contacts'].keys())[0]这种方式获取键值非常脆弱,若返回的JSON结构变化会直接报错。同时捕获所有except:会掩盖真正的错误原因,不利于调试。多余的阻塞输入
input('Press ENTER to exit')在被subprocess调用时会导致脚本卡住,无法正常输出结果并退出。
优化后的完整代码示例
改进后的Bot代码
import discord import subprocess from discord.ext import commands # 替换为你的Bot令牌 BOT_TOKEN = "TOKEN_VALUE" # 查询脚本的路径 SCRIPT_PATH = "query_script.py" # 使用commands框架更方便处理命令参数 bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) @bot.event async def on_ready(): print(f"已登录为 {bot.user.name}") @bot.command(name="run_script") async def run_script(ctx, wallet_address: str): try: # 通过命令行参数传递钱包地址给查询脚本,避免修改原文件 result = subprocess.run( ["python", SCRIPT_PATH, wallet_address], capture_output=True, text=True, timeout=10 # 设置超时,防止脚本卡住 ) # 合并标准输出和标准错误 output = result.stdout + result.stderr await ctx.send(f"脚本输出:\n```\n{output}\n```") except subprocess.TimeoutExpired: await ctx.send("脚本运行超时,请稍后重试") except Exception as e: await ctx.send(f"运行脚本时出错: {str(e)}") bot.run(BOT_TOKEN)
改进后的查询脚本(重命名为query_script.py)
import requests import json import sys def resolve_wallet(address): url = f"https://meta-api.reddit.com/crypto-contacts?providers=ethereum&addresses={address}" try: response = requests.get(url, timeout=5) response.raise_for_status() # 触发HTTP错误码的异常 data = response.json() contacts = data.get('contacts', {}) if not contacts: return f"{address} 未找到关联用户,可能不是有效地址" # 遍历所有联系人(处理多个结果的情况) for addr_info in contacts.values(): if addr_info and 'username' in addr_info[0]: return f"{address} 关联用户: u/{addr_info[0]['username']}" return f"{address} 未找到有效用户名" except requests.exceptions.RequestException as e: return f"{address} 请求失败: {str(e)}" except (KeyError, IndexError) as e: return f"{address} 解析失败: 数据格式异常" if __name__ == "__main__": if len(sys.argv) < 2: print("请提供钱包地址作为命令行参数") sys.exit(1) wallet_addr = sys.argv[1] print(resolve_wallet(wallet_addr))
关键优化点说明
- 采用
discord.ext.commands框架处理命令,自动解析参数并处理错误,比原生on_message更简洁可靠。 - 通过命令行参数传递钱包地址,彻底避免修改原脚本文件的风险。
- 为网络请求和脚本运行添加超时限制,防止无限阻塞。
- 具体捕获特定异常,便于排查问题,同时避免掩盖未知错误。
- 移除了所有会导致阻塞的
input()调用,确保脚本能被subprocess正常调用并返回结果。
内容的提问来源于stack exchange,提问作者Tom Hutchison

