subprocess.Popen管道如何在Python中工作?

我完全意识到相关问题的存在,但他们都非常模糊,并且未能清楚地解释每一步的进展。 所提供的例子通常没有经过测试,并且没有提供关于如何使它们适应不同场景的信息。 以下是问题以及Python的文档:

  • 如何使用subprocess.Popen通过管道连接多个进程?
  • 用管道连接几个Popen命令
  • https://docs.python.org/2/library/subprocess.html#popen-objects
  • 这基本上是我想要实现的,但在Python中:

    curl http://asdf.com/89asdf.gif | convert -resize 80x80 - - | icat -k -
    

    下面是我花了几个小时将以上答案的部分和部分进行了总结:

    import requests
    import subprocess
    from subprocess import Popen, PIPE, STDOUT
    url = 'http://asdf.com/89asdf.gif'
    img = requests.get(url)
    p1 = subprocess.Popen(['convert', '-resize', '80x80', '-', '-'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    p2 = subprocess.Popen(['icat', '-k', '-'], stdin=p1.stdout, stdout=subprocess.PIPE)
    p1.communicate(img.content)
    print p2.stdout
    

    这是我的代码,这次根据你的回答进行了改进:

    import requests
    from subprocess import Popen, PIPE, STDOUT
    url = 'http://asdf.com/89asdf.gif'
    img = requests.get(url)
    p1 = Popen(['convert', '-resize', '80x80', '-', '-'], stdin=PIPE, stdout=PIPE)
    p2 = Popen(['icat', '-k', '-'], stdin=p1.stdout, stdout=PIPE)
    p1.stdin.write(img.content)
    p1.stdin.close()
    p1.stdout.close()
    output = p2.communicate()[0]
    print output
    

    注意: icat输出256色端子的图像。 我已经设法在另一个问题上成功地打印输出。 在icat处理过的终端中,典型的图像看起来像这样:

    请纠正我错在哪里,但这是我目前的理解:

  • p1.communicate(img.content) :设置p1的STDIN。
  • p1的STDIN是subprocess.PIPE ,这是什么p1.communicate(mg.content)提供。
  • p2的STDIN是p1的STDOUT,它是通过convert调整大小的图像。
  • 然后我printp2的STDOUT,这应该是icat提供的ASCII颜色的图像。
  • 问题:

  • 我见过stdin=subprocess.PIPEstdin=PIPE 。 有什么不同?
  • 为什么在定义其他子流程之后提供的第一个STDIN?
  • 有人能解释过程中究竟发生了什么,以及我的代码出了什么问题? 这整个管道业务必须比看起来简单,我很想知道它是如何工作的。


    Q1。 无论是subprocess.PIPE还是PIPE ,它们都引用相同的符号,这是来自subprocess模块的PIPE 。 以下内容完全相同:

    # Version 1
    import subprocess
    proc = subprocess.Popen(['ls'], stdout=subprocess.PIPE)
    output = proc.communicate()[0]
    
    # Version 2
    from subprocess import PIPE, Popen
    proc = Popen(['ls'], stdout=PIPE)
    output = proc.communicate()[0]
    

    Q2。 communicate()实际上是在将输入发送到p1的STDIN流中。 尽管在调用Popen构造函数时子进程确实存在并且正在运行,但在您的特定情况下, convert实用程序似乎在实际通过STDIN接收内容之前不会执行任何操作。 如果它是一个交互性较低的命令(例如ls ),那么它不会等到communicate()做任何事情。

    更新的内容在你的情况下,而不是使用communicate发送输入到P1,而是尝试以下内容:

    p1.stdin.write(img.content)
    p1.stdin.close()
    p1.stdout.close() # Protect against the busted pipe condition when p2 finishes before p1
    output = p2.communicate()[0]
    print output
    

    看看你有没有更好的运气。


    Q1。 没有区别,他们都是subprocess.PIPE ....

    Q2。 你不必这样做,你可以轻松做到这一点

    p1.stdin.write(img.content)
    

    (事实上​​,那正是通信的那部分......)

    communicate被使用,因为它阻塞直到进程结束(在这种情况下,所以它的标准输出可以提供给p2.stdin(也许?)), write只需写入管道并继续到文件中的下一行python

    链接地址: http://www.djcxy.com/p/77089.html

    上一篇: How do subprocess.Popen pipes work in Python?

    下一篇: invoking pipe command with Popen in Python