Pycord发送带本地缩略图的Embed到指定频道报IO关闭文件错误
问题根因
抛出ValueError: I/O operation on closed file的核心原因是你复用了已经被关闭IO流的discord.File实例。
Pycord在完成文件上传发送后,会自动关闭discord.File绑定的底层文件指针。你现在把localThumbnail实例定义在回调外层,只要这个实例之前被用于过其他发送场景(比如交互触发时先在当前频道发了消息、或者私信场景已经用过一次这个File对象),后续再拿这个已经关闭流的实例跨频道发送,就会触发读文件失败的错误。这也是为什么同一份逻辑在当前频道、私信场景能用,跨频道发就报错——前者是第一次使用File实例,流是正常打开状态,后者是复用已经被关闭的实例。
另外你的代码里混入了interactions库的导入语句,interactions.py是和Pycord独立的另一套Discord机器人开发框架,混导容易引发类不兼容的隐性问题,建议删除。
排查方向
- 检查
localThumbnail的定义位置:如果是在按钮交互回调的外层全局定义,且在跨频道发送前已经被其他发送逻辑调用过,就会出现流被提前关闭的问题。 - 校验附件引用匹配性:
attachment://协议后的文件名必须和传入send方法的discord.File的文件名完全一致,当前代码的命名匹配是正确的,这部分不需要调整。 - 排查手动关闭流的逻辑:确认代码中没有手动调用
localThumbnail.close()的操作,同时确认本地图片路径在程序运行时的访问权限正常,不存在文件打开失败的情况。
修复方案
不要提前实例化全局复用的discord.File对象,只把固定的文件路径、附件引用URI抽为常量,每次执行发送操作前重新实例化新的discord.File对象即可,新实例会重新打开本地文件流,不会出现流关闭的问题。
修正后的核心代码:
import discord from discord.ui import Select, View, Button from discord.utils import get # 仅抽固定配置为常量,不要提前实例化discord.File THUMBNAIL_PATH = "./Source/Images/thumbnail-placeholder.png" THUMBNAIL_ATTACH_REF = "attachment://thumbnail-placeholder.png" # 发送逻辑内每次新建File实例 embedConfirm.set_thumbnail(url=THUMBNAIL_ATTACH_REF) local_thumbnail = discord.File(THUMBNAIL_PATH) target_channel = bot.get_channel(int(ADMINREPORTCHANNEL)) await target_channel.send(embed=embedConfirm, view=view, file=local_thumbnail)
注意:如果需要同时向当前交互频道、目标管理频道发送同一份带缩略图的消息,必须为两次send操作分别实例化独立的
discord.File对象,绝对不能复用同一个实例,每次send完成后Pycord都会自动关闭对应文件的IO流,复用必然触发本次的报错。
内容的提问来源于stack exchange,提问作者JumpMan
相关产品推荐
相关产品推荐

