Python子流程:将图像blob管道化到imagemagick shell命令

Python子流程:将图像blob管道化到imagemagick shell命令,python,image,shell,imagemagick,subprocess,Python,Image,Shell,Imagemagick,Subprocess,我的内存中有一个图像,我希望使用Python的子进程执行imagemagick的convert方法。虽然这一行在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.co

我的内存中有一个图像,我希望使用Python的
子进程执行imagemagick的
convert
方法。虽然这一行在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的情况下将图像作为常规文件读取,我尝试了在
子进程
方法和不同的写入stdin的方式之间切换

最棒的是,什么都没有发生,但我没有得到一个真正的错误。打印标准输出时,我可以在终端上看到imagemagick帮助,然后是以下内容:

默认情况下,“文件”的图像格式由其魔力决定 号码。要指定特定的图像格式,请在文件名之前 使用图像格式名称和冒号(即ps:image)或指定 图像类型作为文件名后缀(即image.ps)。将“文件”指定为 “-”用于标准输入或输出。(没有,没有)

也许这里有个暗示我不明白。 请给我指出正确的方向,我是Python新手,但从我使用PHP的经验来看,这应该是一项非常简单的任务,至少我希望如此

编辑:

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


引起任何问题的不是子流程,而是您传递给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_调用,如果存在非零退出状态,您可以捕获并采取适当的操作,该调用将引发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)
如果要使用communicate写入stdin,还可以使用.read:

with  open('image.jpg') as jpgfile:
     proc = Popen(['convert', '-', 'new_image.jpg'], stdin=PIPE)
     proc.communicate(jpgfile.read())
如果您不想将映像存储在磁盘上,请使用

使用对象:


这对我没有帮助,因为我想从内存中传递一个映像,而不必在磁盘上创建物理拷贝。您所有的示例都与读取图像文件有关。试图将图像对象传递给stdin不起作用,正如我在问题中所描述的,什么也没有发生。那么图像来自哪里?我使用代理通过HTTP读取图像,我想使用blob本身创建图像的优化版本,而不必将原始图像保存在磁盘上。我知道在使用其他编程语言时这不应该是一个问题,我不知道如何使用Python实现它。谢谢!我使用了一个稍有不同的解决方案,因为我需要使用PIL image对象,但您的回答肯定让我找到了正确的方向。@伊莫西斯,不用担心,我不完全确定数据来自何处,但我认为逻辑大致相同。
with  open('image.jpg') as jpgfile:
     proc = Popen(['convert', '-', 'new_image.jpg'], stdin=PIPE)
     proc.communicate(jpgfile.read())
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)
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())