使用discord.py修改角色图标报错,求原因及解决方法
问题:Discord.py 修改角色图标时触发 TypeError 错误
我使用discord.py开发Discord机器人,编写了以下命令用于修改指定ID角色的图标:
@bot.command(name='role') async def role(ctx, role_id, new_icon_url): new_icon_url = str(new_icon_url) if new_icon_url.count('<:') != 0: new_icon_url = new_icon_url.split(':') new_icon_url = new_icon_url[2] new_icon_url = new_icon_url.replace('>', '') new_icon_url = 'https://cdn.discordapp.com/emojis/%{placeholder}%.png'.replace('%{placeholder}%', new_icon_url) role = discord.utils.get(ctx.guild.roles, id=int(role_id)) if role is not None: try: await role.edit(display_icon=new_icon_url) await ctx.send(f"Role icon for {role.name} has been updated.") except discord.errors.Forbidden: await ctx.send("I don't have the required permissions to edit role icons.") else: await ctx.send(f"Role with ID {role_id} not found.")
但执行命令时触发了如下错误:
Traceback (most recent call last): File "C:\Users\VosQu\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\discord\ext\commands\core.py", line 235, in wrapped ret = await coro(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "c:\Users\VosQu\OneDrive\Desktop\Brewy Poo\brew.py", line 271, in role new_icon_url = bytes(new_icon_url) ^^^^^^^^^^^^^^^^^^^ TypeError: string argument without an encoding The above exception was the direct cause of the following exception: Traceback (most recent call last): File "C:\Users\VosQu\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\discord\ext\commands\bot.py", line 1350, in invoke await ctx.command.invoke(ctx) File "C:\Users\VosQu\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\discord\ext\commands\core.py", line 1029, in invoke await injected(*ctx.args, **ctx.kwargs) # type: ignore ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\VosQu\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\discord\ext\commands\core.py", line 244, in wrapped raise CommandInvokeError(exc) from exc discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: string argument without an encoding
原本预期命令能成功修改角色图标,但实际返回上述错误,请问原因是什么?
原因分析与修复方案
1. 直接错误原因:字符串转Bytes未指定编码
错误栈明确指向代码第271行的new_icon_url = bytes(new_icon_url)——Python中把字符串转成bytes对象必须指定编码格式(比如utf-8),否则会触发TypeError。如果这行是你主动添加的,要么删除它,要么修正为:
new_icon_url = bytes(new_icon_url, 'utf-8') # 指定编码
但这只是解决了表面的语法错误,核心问题是你误解了role.edit()方法中display_icon参数的要求。
2. 核心问题:display_icon不支持直接传入URL
discord.py的Role.edit()方法的display_icon参数不接受普通URL字符串,它只接受以下三种类型的输入:
bytes:图片的二进制数据io.BufferedIOBase:文件流对象(比如io.BytesIO)str:Base64编码的图片字符串(格式为data:image/png;base64,xxxxxx)
3. 修复后的完整代码示例
要实现从URL修改角色图标的功能,你需要先下载图片内容,再转换成符合要求的格式传入。以下是使用aiohttp下载图片并以File对象传入的示例:
import aiohttp from io import BytesIO from discord import File @bot.command(name='role') async def role(ctx, role_id, new_icon_url): # 处理表情符号转CDN URL的逻辑 if '<:' in new_icon_url: emoji_parts = new_icon_url.split(':') emoji_id = emoji_parts[2].replace('>', '') new_icon_url = f'https://cdn.discordapp.com/emojis/{emoji_id}.png' # 获取目标角色 role = discord.utils.get(ctx.guild.roles, id=int(role_id)) if not role: await ctx.send(f"找不到ID为{role_id}的角色。") return try: # 异步下载图片内容 async with aiohttp.ClientSession() as session: async with session.get(new_icon_url) as resp: if resp.status != 200: await ctx.send("图片下载失败,请检查URL是否有效。") return image_data = await resp.read() # 将二进制数据包装成File对象传入 await role.edit(display_icon=File(BytesIO(image_data), 'role_icon.png')) await ctx.send(f"{role.name}的角色图标已更新。") except discord.errors.Forbidden: await ctx.send("我没有修改角色图标的权限。") except Exception as e: await ctx.send(f"更新失败:{str(e)}")
4. 其他可选方案:使用Base64编码
如果你不想用File对象,也可以将图片转成Base64编码字符串传入:
import base64 # 在下载到image_data后: base64_str = base64.b64encode(image_data).decode('utf-8') await role.edit(display_icon=f"data:image/png;base64,{base64_str}")
内容的提问来源于stack exchange,提问作者VosQuz
相关产品推荐
相关产品推荐

