Подпроцесс Python: проведите кадр изображения в команду imagemagick shell

У меня есть изображение в памяти, и я хочу выполнить метод convert imagemagick с использованием subprocess Python. Хотя эта линия хорошо работает с терминалом Ubuntu:

cat image.png | convert - new_image.jpg

Этот кусок кода не работает с использованием Python:

 jpgfile = Image.open('image.png'); proc = Popen(['convert', '-', 'new_image.jpg'], stdin=PIPE, shell=True) print proc.communicate(jpgfile.tostring()) 

Я также пробовал читать изображение как обычный файл без использования PIL, я пробовал переключение между методами subprocess и разными способами записи в stdin.

Лучшая часть – ничего не происходит, но я не получаю реальной ошибки. Когда вы печатаете stdout, я вижу обратную помощь на терминале, а затем следующее:

По умолчанию формат файла `file 'определяется его магическим числом. Чтобы указать конкретный формат изображения, перед именем файла укажите имя формата изображения и двоеточие (например, ps: изображение) или укажите тип изображения в качестве суффикса имени файла (например, image.ps). Укажите «файл» как «-» для стандартного ввода или вывода. (Нет, Нет)

Может быть, здесь есть намек, который я не получаю. Пожалуйста, укажите мне в правильном направлении, я новичок в Python, но из моего опыта работы с PHP это должно быть очень простой задачей, или я надеюсь.

Редактировать:

Это решение, которое я в конечном итоге использовал для обработки объекта изображения PIL без сохранения временного файла. Надеюсь, это поможет кому-то. (в примере я читаю файл с локального диска, но идея состоит в том, чтобы прочитать изображение из удаленного места)

 out = StringIO() jpgfile = Image.open('image.png') jpgfile.save(out, 'png', quality=100); out.seek(0); proc = Popen(['convert', '-', 'image_new.jpg'], stdin=PIPE) proc.communicate(out.read()) 

Это не подпроцесс, вызывающий какую-либо проблему, это то, что вы передаете imagemagick, что неверно, tostring() передается в imagemagick . если вы действительно хотели реплицировать команду linux, вы можете переходить из одного процесса в другой:

 from subprocess import Popen,PIPE proc = Popen(['cat', 'image.jpg'], stdout=PIPE) p2 = Popen(['convert', '-', 'new_image.jpg'],stdin=proc.stdout) proc.stdout.close() out,err = proc.communicate() print(out) 

Когда вы передаете список аргументов, вам не требуется shell = True, если вы хотите использовать shell = True, вы должны передать одну строку:

 from subprocess import check_call check_call('cat image.jpg | convert - new_image.jpg',shell=True) 

Обычно я бы избегал shell=True . Этот ответ описывает, что именно shell = True делает.

Вы также можете передать файл-объект в stdin:

 with open('image.jpg') as jpgfile: proc = Popen(['convert', "-", 'new_image.jpg'], stdin=jpgfile) out, err = proc.communicate() print(out) 

Но так как нет результата при успешном выполнении кода, вы можете использовать check_call, который повысит CalledProcessError, если есть ненулевой статус выхода, который вы можете поймать и предпринять соответствующие действия:

 from subprocess import check_call, CalledProcessError with open('image.jpg') as jpgfile: try: check_call(['convert', "-", 'new_image.jpg'], stdin=jpgfile) except CalledProcessError as e: print(e.message) 

Если вы хотите написать в stdin, используя связь, вы также можете передать содержимое файла, используя .read:

 with open('image.jpg') as jpgfile: proc = Popen(['convert', '-', 'new_image.jpg'], stdin=PIPE) proc.communicate(jpgfile.read()) 

Если вы хотите, не хотите хранить изображение на диске, используйте tempfile:

 import tempfile import requests r = requests.get("http://www.reptileknowledge.comhttp://img.rupython.com/pythonball-python.jpg") out = tempfile.TemporaryFile() out.write(r.content) out.seek(0) from subprocess import check_call check_call(['convert',"-", 'new_image.jpg'], stdin=out) 

Использование объекта CStringIo.StringIO :

 import requests r = requests.get("http://www.reptileknowledge.comhttp://img.rupython.com/pythonball-python.jpg") out = cStringIO.StringIO(r.content) from subprocess import check_call,Popen,PIPE p = Popen(['convert',"-", 'new_image.jpg'], stdin=PIPE) p.communicate(out.read())