简体   繁体   English

在python中正确使用subprocess.PIPE?

[英]Properly using subprocess.PIPE in python?

I'm trying to use subprocess.Popen to construct a sequence to grab the duration of a video file. 我正在尝试使用subprocess.Popen构建一个序列来获取视频文件的持续时间。 I've been searching for 3 days, and can't find any reason online as to why this code isn't working, but it keeps giving me a blank result: 我一直在搜索3天,并且在网上找不到任何原因,为什么这段代码不起作用,但它一直给我一个空白的结果:

import sys
import os
import subprocess

def main():
  the_file = "/Volumes/Footage/Acura/MDX/2001/Crash Test/01 Acura MDX Front Crash.mov"
  ffmpeg = subprocess.Popen(['/opt/local/bin/ffmpeg', '-i', the_file], stdout = subprocess.PIPE, )
  grep = subprocess.Popen(['grep', 'Duration'], stdin = subprocess.PIPE, stdout = subprocess.PIPE, )
  cut = subprocess.Popen(['cut', '-d', ' ', '-f', '4'], stdin = subprocess.PIPE, stdout = subprocess.PIPE, )
  sed = subprocess.Popen(['sed', 's/,//'], stdin = subprocess.PIPE, stdout = subprocess.PIPE, )

  duration = sed.communicate()
  print duration

if __name__ == '__main__':
  main()

As others have pointed out, you need to pass the PIPE from one process to the next. 正如其他人所指出的那样,您需要将PIPE从一个进程传递到下一个进程。 The stdout (PIPE) from one process becomes the stdin for the following task. 来自一个进程的stdout(PIPE)成为以下任务的stdin。

Something like this (starting from your example): 这样的事情(从你的例子开始):

import sys
import os
import subprocess

def main():
  the_file = "/Volumes/Footage/Acura/MDX/
              2001/Crash Test/01 Acura MDX Front Crash.mov"
  ffmpeg = subprocess.Popen(['/opt/local/bin/ffmpeg', '-i', the_file],
                            stdout = subprocess.PIPE)
  grep = subprocess.Popen(['grep', 'Duration'], 
                          stdin = ffmpeg.stdout, stdout = subprocess.PIPE)
  cut = subprocess.Popen(['cut', '-d', ' ', '-f', '4'],
                         stdin = grep.stdout, stdout = subprocess.PIPE)
  sed = subprocess.Popen(['sed', 's/,//'],
                         stdin = cut.stdout, stdout = subprocess.PIPE)

  duration = sed.communicate()[0]
  print duration

if __name__ == '__main__':
  main()

stderr needs to be redirected to stdout. stderr需要重定向到stdout。 Also, there's no need to call other tools like cut/sed etc. do your string manipulation in Python 此外,没有必要调用其他工具,如cut/sed等,在Python中进行字符串操作

import subprocess
....
the_file = "/Volumes/Footage/Acura/MDX/2001/Crash Test/01 Acura MDX Front Crash.mov"
ffmpeg = subprocess.Popen(['/usr/bin/ffmpeg', '-i', the_file], stderr=subprocess.STDOUT,stdout = subprocess.PIPE )
out, err = ffmpeg.communicate()
if "Duration" in out:
    print out[out.index("Duration"):].split()[1]

If Python is not a must, you can use the shell directly. 如果Python不是必须的,您可以直接使用shell。

the_file="/Volumes/Footage/Acura/MDX/2001/Crash Test/01 Acura MDX Front Crash.mov"
ffmpeg -i "$file" 2>&1 | awk '/Duration/{print $2}'

Using subprocess.PIPE will not magically wire the correct pipes for you. 使用subprocess.PIPE不会为您神奇地连接正确的管道。

You must pass the output pipe of the first process as the value for the parameter stdin of the second process. 必须将第一个进程的输出管道作为第二个进程的参数stdin的值传递。 See the docs for an example . 请参阅文档以获取示例

Python can't "build a whole pipeline" in this way -- it could delegate the task to the shell, or glue it up more directly using the stdout attributes of previous subprocess objects in the line, but there's really no reason for that in this specific case, since you can code it directly in Python pretty easily. Python无法以这种方式“构建整个管道” - 它可以将任务委托给shell,或者使用行中先前子进程对象的stdout属性更直接地粘贴它,但实际上没有理由在这个特例,因为你可以很容易地直接用Python编写代码。 Eg: 例如:

  ffmpeg = subprocess.Popen(['/opt/local/bin/ffmpeg', '-i', the_file],
                            stdout=subprocess.PIPE)
  for line in ffmpeg.stdout:
    if 'Duration' not in line: continue
    fields = line.split()
    duration = fields[4].replace(',', '')
    break

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM