Отправить несколько строк из PIL-изображения в POST-запросах с помощью Python

#python #image #post #python-imaging-library #stringio

#python #изображение #Публикация #python-imaging-library #stringio

Вопрос:

У меня есть сохраненное изображение на моем компьютере. Я открываю его с помощью модуля Python Image. Затем я обрезаю это изображение на несколько частей, используя этот модуль. В заключение я хотел бы загрузить изображение с помощью POST-запроса на веб-сайте.

Поскольку эти небольшие изображения являются объектом PIL, я преобразовал каждое из них в StringIO, чтобы иметь возможность отправлять форму без необходимости сохранять их на моем компьютере.

К сожалению, я сталкиваюсь с ошибкой, тогда как, если изображения физически хранятся на моем компьютере, проблем нет. Я не понимаю, почему.

Вы можете посетить веб-сайт здесь: http://www.noelshack.com/api.php Это очень простой API, который возвращает ссылку на загруженное изображение. В моем случае проблема в том, что в конце второго изображения ничего не возвращается (для первого проблем нет).


Вот программный код для обрезки изображения на 100 частей.

 import requests
import Image
import StringIO
import os

image = Image.open("test.jpg")
width, height = image.size

images = []

for i in range(10):
    for j in range(10):
        crop = image.crop((i * 10, j * 10, (i   1) * 10, (j   1) * 10))
        images.append(crop)
  

Функция для загрузки изображения:

 def upload(my_file):
    api_url = 'http://www.noelshack.com/api.php'
    r = requests.post(api_url, files={'fichier': my_file})

    if not 'www.noelshack.com' in r.text:
        raise Exception(r.text)

    return r.text
  

Теперь у нас есть две возможности. Первый — сохранить каждое из 100 изображений на диске и загрузить их.

 if not os.path.exists("directory"):
    os.makedirs("directory")

i = 0
for img in images:
    img.save("directory/"   str(i)   ".jpg")
    i  = 1

for file in os.listdir("directory"):
    with open("directory/"   file, "rb") as f:
        print upload(f)
  

Это работает как шарм, но не очень удобно. Итак, я решил использовать StringIO.

 for img in images:
    my_file = StringIO.StringIO()
    img.save(my_file, "JPEG")
    print upload(my_file.getvalue())
    # my_file.close() -> Does not change anything
  

Печатается первая ссылка, но затем функция вызывает исключение.

Я думаю, что проблема заключается в том img.save() , что один и тот же цикл for не работал для сохранения на диск и последующей загрузки. Кроме того, если вы добавите a time.sleep(1) между загрузками, это, похоже, сработает.

Любая помощь будет приветствоваться, пожалуйста, потому что я действительно застрял.

Комментарии:

1. В первом случае физического файла вы передаете upload() открытый file объект изображения, а во втором StringIO случае вы передаете ему содержимое файла изображения.

2. @martineau Что мне делать? И почему второй случай работает для одного или двух изображений, а затем вызывает исключение?

3. Это может сработать, если вы просто передадите ему StringIO объект (с именем my_file ), потому что первые в основном ведут себя как обычные file объекты.

4. @martineau К сожалению, я уже пробовал, и это не удалось. Но это хуже всего, потому что даже первые запросы не работают.

5. Возможно, вам нужно перемотать виртуальный файл на a my_file.seek(0) , прежде чем передавать его upload() .

Ответ №1:

my_file.getvalue() возвращает строку. Что вам нужно, так это файлоподобный объект, которым уже является my_file. И объекты, подобные файлам, имеют, так сказать, курсор, который указывает, откуда читать или куда записывать. Итак, если вы выполните my_file.seek(0) перед загрузкой, это должно быть исправлено.

измените код, чтобы:

 for img in images:
    my_file = StringIO.StringIO()
    img.save(my_file, "JPEG")
    my_file.seek(0)
    print upload(my_file)