首页 > 解决方案 > send_media_group 与 BytesIO 到电报机器人

问题描述

我正在使用 PIL 创建图像并使用 BytesIO 将其存储在剪贴板中。我想将图像相册发送到电报机器人,但出现错误:

代码:

from PIL import Image, ImageDraw, ImageFont
from io import BytesIO
from aiogram import Bot, Dispatcher, executor, types
import logging

API_TOKEN = 'xxxxxx'
logging.basicConfig(level=logging.INFO)
bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot)

def createimg()
    im = Image.new('RGB', (256, 256), color='black')
    bio = BytesIO()
    bio.name = 'res.png'
    im.save(bio, 'PNG')
    bio.seek(0)
    return bio

@dp.message_handler(commands=['start'])
async def send_welcome(message: types.Message):
    await bot.send_media_group(message.from_user.id, [createimg(), createimg()])

错误:

   raise TypeError(f"Media must be an instance of InputMedia or dict, not {type(media).__name__}")
TypeError: Media must be an instance of InputMedia or dict, not BytesIO

标签: python-3.xpython-imaging-librarybytesioaiogram

解决方案


您必须aiogram.types.InputMedia在列表中使用对象的子类,而不是普通io.BytesIO对象。在您的情况下,它必须是aiogram.types.InputMediaPhoto,它接受aiogram.types.InputFileobject 作为第一个参数,您可以io.BytesIO直接在其中放置普通对象。

此外,请考虑在代码中使用快捷方式,因为它可以使您的代码更简洁、更具可读性。例如,您可以.reply().answer()aiogram.types.Message这是 的快捷方式aiogram.Bot.send_message()。在您的情况下,您应该使用aiogram.types.Message.answer_media_group.

所以,你的代码应该是这样的:

# Some code is omitted in favor of brievity

def wrap_media(bytesio, **kwargs):
    """Wraps plain BytesIO objects into InputMediaPhoto"""
    # First, rewind internal file pointer to the beginning so the contents
    #  can be read by InputFile class
    bytesio.seek(0)
    return types.InputMediaPhoto(types.InputFile(bytesio), **kwargs)

@dp.message_handler(commands=['start'])
async def send_welcome(message: types.Message):
    await message.answer_media_group([wrap_media(createimg()), wrap_media(createimg())])

有关aiogram.types.InputMediaPhoto接受内容的更多信息,请参阅aiogram 文档


推荐阅读