Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. 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:

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()
like image 433
Gordon Fontenot Avatar asked Mar 22 '10 16:03

Gordon Fontenot


People also ask

How do you use pipes in subprocess Python?

To use a pipe with the subprocess module, you have to pass shell=True . In your particular case, however, the simple solution is to call subprocess. check_output(('ps', '-A')) and then str. find on the output.

What is subprocess pipe in Python?

Source code: Lib/subprocess.py. The subprocess module allows you to spawn new processes, connect to their input/output/error pipes, and obtain their return codes. This module intends to replace several older modules and functions: os.

How does Popen work in Python?

popen method opens a pipe from a command. This pipe allows the command to send its output to another command. The output is an open file that can be accessed by other programs. Here the command parameter is what you'll be executing, and its output will be available via an open file.

How do you write subprocess in Python?

communicate with input , you need to initiate the subprocess with stdin=subprocess. PIPE according to the docs. Note that if you want to send data to the process's stdin, you need to create the Popen object with stdin=PIPE.


2 Answers

As others have pointed out, you need to pass the PIPE from one process to the next. The stdout (PIPE) from one process becomes the stdin for the following task.

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()
like image 190
KevB Avatar answered Sep 20 '22 16:09

KevB


stderr needs to be redirected to stdout. Also, there's no need to call other tools like cut/sed etc. do your string manipulation in 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.

the_file="/Volumes/Footage/Acura/MDX/2001/Crash Test/01 Acura MDX Front Crash.mov"
ffmpeg -i "$file" 2>&1 | awk '/Duration/{print $2}'
like image 20
ghostdog74 Avatar answered Sep 18 '22 16:09

ghostdog74