如何在discord.py中实现向指定用户发送文件的命令?
Discord.py 文件发送命令参数转换错误解决办法
问题场景
想用discord.py实现一个给指定用户发送文件的命令,但运行代码时出现参数转换错误,相关代码及报错如下:
原代码
@bot.command() async def sendfile(user: discord.User, *, file: discord.File): """Send a file to a user.""" await user.send(content="here you go", file=discord.File(file))
报错信息
Traceback (most recent call last): File "C:\Users\berka\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\ext\commands\converter.py", line 1233, in _actual_conversion return converter(argument) ^^^^^^^^^^^^^^^^^^^ File "C:\Users\berka\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\file.py", line 97, in __init__ self.fp = open(fp, 'rb') ^^^^^^^^^^^^^^ OSError: [Errno 22] Invalid argument: '<@1065847074253443205>' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "C:\Users\berka\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\ext\commands\bot.py", line 1350, in invoke await ctx.command.invoke(ctx) File "C:\Users\berka\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\ext\commands\core.py", line 1015, in invoke await self.prepare(ctx) File "C:\Users\berka\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\ext\commands\core.py", line 932, in prepare await self._parse_arguments(ctx) File "C:\Users\berka\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\ext\commands\core.py", line 839, in _parse_arguments transformed = await self.transform(ctx, param, attachments) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\berka\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\ext\commands\core.py", line 709, in transform return await run_converters(ctx, converter, argument, param) # type: ignore ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\berka\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\ext\commands\converter.py", line 1342, in run_converters return await _actual_conversion(ctx, converter, argument, param) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\berka\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\ext\commands\converter.py", line 1242, in _actual_conversion raise BadArgument(f'Converting to "{name}" failed for parameter "{param.name}".') from exc discord.ext.commands.errors.BadArgument: Converting to "File" failed for parameter "file".
错误原因
- 参数转换器不支持直接转
discord.File:discord.py的命令参数系统无法将用户输入的字符串(比如调用命令时输入的用户ID或文件名)自动转换为discord.File对象,它会把输入的字符串当作文件路径去打开,而你输入的是用户ID(<@1065847074253443205>),自然会报无效路径的错误。 - 重复创建
discord.File对象:就算参数转换成功,原代码里discord.File(file)也是多余操作,因为file已经是discord.File对象,再传入会导致内部尝试打开它的文件指针时出错。
解决办法
方案1:通过命令附件发送文件(推荐)
让用户调用命令时附带文件,从消息附件中获取文件发送:
@bot.command() async def sendfile(ctx, user: discord.User): """给指定用户发送命令附带的文件""" if not ctx.message.attachments: await ctx.send("请附带要发送的文件!") return # 获取第一个附件并转换为discord.File对象 attachment = ctx.message.attachments[0] file = await attachment.to_file() # 发送给目标用户 await user.send(content="给你文件", file=file) await ctx.send("文件已成功发送!")
方案2:发送本地文件(机器人需有文件读取权限)
如果要发送机器人所在服务器的本地文件,让用户提供文件路径:
@bot.command() async def sendfile(ctx, user: discord.User, *, file_path: str): """给指定用户发送本地文件(需提供文件路径)""" try: file = discord.File(file_path) await user.send(content="给你文件", file=file) await ctx.send("文件已成功发送!") except OSError as e: await ctx.send(f"读取文件失败:{str(e)}")
内容的提问来源于stack exchange,提问作者Codermaster1231
相关产品推荐
相关产品推荐

