Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在python中正确使用subprocess.PIPE?_Python_Subprocess - Fatal编程技术网

在python中正确使用subprocess.PIPE?

在python中正确使用subprocess.PIPE?,python,subprocess,Python,Subprocess,我试图使用subprocess.Popen构造一个序列来获取视频文件的持续时间。我已经搜索了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([

我试图使用
subprocess.Popen
构造一个序列来获取视频文件的持续时间。我已经搜索了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()

使用
subprocess.PIPE
不会神奇地为您连接正确的管道

必须将第一个进程的输出管道作为第二个进程的参数
stdin
的值传递

Python不能以这种方式“构建一个完整的管道”——它可以将任务委托给shell,或者更直接地使用行中先前子流程对象的
stdout
属性将其粘合起来,但是在这种特定情况下确实没有理由这样做,因为您可以非常轻松地直接用Python编写它。例如:

  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

stderr需要重定向到stdout。此外,不需要调用其他工具,如
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]
如果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}'

正如其他人指出的,您需要将管道从一个流程传递到下一个流程。 来自一个进程的标准输出(管道)将成为以下任务的标准输入

类似这样的内容(从您的示例开始):


为什么要使用grep、cut和sed来解析输出,而不是使用内置的Python函数?你的敌人是你。我没有意识到我必须重定向<代码> STDRR 。我会认为这是正确的答案,它准确地回答了OP所问的问题,并没有告诉你如何绕过它。现在有一个管道模块:
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()