Python子进程:将图像blob传递给imagemagick shell命令 [英] Python subprocess: pipe an image blob to imagemagick shell command

查看:280
本文介绍了Python子进程:将图像blob传递给imagemagick shell命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在内存中有一个图像,我希望使用Python的子进程执行imagemagick的 convert 方法。虽然这条线在Ubuntu的终端上运行良好:

I have an image in-memory and I wish to execute the convert method of imagemagick using Python's subprocess. While this line works well using Ubuntu's terminal:

cat image.png | convert - new_image.jpg

这段代码无法使用Python:

This piece of code doesn't work using Python:

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

我还尝试在不使用PIL的情况下将图像作为常规文件读取,我尝试在<$之间切换c $ c> subprocess 方法和写入stdin的不同方法。

I've also tried reading the image as a regular file without using PIL, I've tried switching between subprocess methods and different ways to write to stdin.

最好的部分是,没有发生任何事情,但我没有得到一个真正的错误。打印stdout时,我可以在终端上看到imagemagick帮助,然后是以下内容:

The best part is, nothing is happening but I'm not getting a real error. When printing stdout I can see imagemagick help on terminal, followed by the following:


默认情况下,确定`file'的图像格式通过其神奇的
数字。要指定特定的图像格式,请在文件名
之前添加图像格式名称和冒号(即ps:image),或将
图像类型指定为文件名后缀(即image.ps)。对于标准输入或输出,将'file'指定为
' - '。 (无,无)

By default, the image format of `file' is determined by its magic number. To specify a particular image format, precede the filename with an image format name and a colon (i.e. ps:image) or specify the image type as the filename suffix (i.e. image.ps). Specify 'file' as '-' for standard input or output. (None, None)

也许这里有一个暗示,我没有得到。
请指出我正确的方向,我是Python的新手,但根据我对PHP的经验,这应该是一项非常简单的任务,或者我希望如此。

Maybe there's a hint in here I'm not getting. Please point me in the right direction, I'm new to Python but from my experience with PHP this should be an extremely easy task, or so I hope.

编辑:

这是我最终用于处理PIL图像对象而不保存临时文件的解决方案。希望它可以帮到某人。 (在示例中,我正在从本地驱动器读取文件,但想法是从远程位置读取图像)

This is the solution I eventually used to process PIL image object without saving a temporary file. Hope it helps someone. (in the example I'm reading the file from the local drive, but the idea is to read an image from a remote location)

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命令,你可以从一个进程管道到另一个进程:

It is not subprocess that is causing any issue it is what you are passing to imagemagick that is incorrect,tostring() does get passed to imagemagick. if you actually wanted to replicate the linux command you can pipe from one process to another:

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)

当你传递一个args列表时,你不需要shell = True,如果你想使用shell = True你会传递一个字符串:

When you pass a list of args you don't need shell=True, if you wanted to use shell=True you would pass a single string:

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

一般我会避免 shell = True 。这个答案概述了shell = True的确切含义。

Generally I would avoid shell=True. This answer outlines what exactly shell=True does.

你也可以将文件对象传递给stdin:

You can also pass a file object to stdin:

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

out, err = proc.communicate()

print(out)

但由于代码成功运行时没有输出你可以使用check_call来提升CalledProcessError如果存在非零退出状态,您可以捕获并执行相应的操作:

But as there is no output when the code runs successfully you can use check_call which will raise a CalledProcessError if there is a non-zero exit status which you can catch and take the appropriate action:

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)

如果你想使用comm写入stdin unicate你也可以使用.read传递文件内容:

If you wanted to write to stdin using communicate you could also pass the file contents using .read:

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

如果您不想将图像存储在磁盘上,请使用 tempfile:

If you want don't want to store the image on disk use a tempfile:

import tempfile
import requests

r = requests.get("http://www.reptileknowledge.com/images/ball-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.com/images/ball-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())

这篇关于Python子进程:将图像blob传递给imagemagick shell命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆