Отправить изображение из памяти - PullRequest
2 голосов
/ 31 января 2020

Я пытаюсь внедрить систему для бота Discord, которая динамически изменяет изображения и отправляет их пользователям бота. Для этого я решил использовать библиотеку Pillow (PIL), поскольку она показалась мне простой и понятной.

Вот пример моего рабочего кода. Он загружает пример изображения, в качестве тестовой модификации, dr aws две диагональные линии на нем и выводит изображение в виде сообщения Discord:

# Open source image
img = Image.open('example_image.png')

# Modify image
draw = ImageDraw.Draw(img)
draw.line((0, 0) + img.size, fill=128)
draw.line((0, img.size[1], img.size[0], 0), fill=128)

# Save to disk and create discord file object
img.save('tmp.png', format='PNG')
file = discord.File(open('tmp.png', 'rb'))

# Send picture as message
await message.channel.send("Test", file=file)

Это приводит к следующему сообщению от моего бота:

Discord message with the edited image as result

Это работает; однако я хотел бы пропустить этап сохранения изображения на жесткий диск и загрузки его снова, так как это кажется довольно неэффективным и ненужным. После некоторого поиска в Google я наткнулся на следующее решение; однако, это не похоже на работу:

# Save to disk and create discord file object
# img.save('tmp.png', format='PNG')
# file = discord.File(open('tmp.png', 'rb'))

# Save to memory and create discord file object
arr = io.BytesIO()
img.save(arr, format='PNG')
file = discord.File(open(arr.getvalue(), 'rb'))

Это приводит к следующему сообщению об ошибке:

Traceback (most recent call last):
    File "C:\Users\<username>\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\client.py", line 270, in _run_event
        await coro(*args, **kwargs)
    File "example_bot.py", line 48, in on_message
        file = discord.File(open(arr.getvalue(), 'rb'))
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte

1 Ответ

2 голосов
/ 31 января 2020

discord.File поддерживает передачу io.BufferedIOBase в качестве параметра fp.
io.BytesIO наследуется от io.BufferedIOBase.
Это означает, что вы можете напрямую передать экземпляр io.BytesIO как fp для инициализации discord.File, например:

arr = io.BytesIO()
img.save(arr, format='PNG')
arr.seek(0)
file = discord.File(arr)

Другой пример этого можно увидеть в Как мне загрузить изображение? раздел FAQ в документации discord.py .

...