Subprocesso Python + Mencoder não está funcionando, o mesmo comando funciona no terminal
-
25-09-2019 - |
Pergunta
Estou tendo um problema em usar o Mencoder (SVN-R30531-4.2.1) através de um subprocesso Python (2.6.1). Estou tentando ingressar em dois arquivos MP4, que são exatamente do mesmo tamanho, codec etc. Ambos não têm áudio. O código que estou usando para testar é:
import subprocess
mp4merge = [ "mencoder", "in1.mp4", "in2.mp4", "-ovc", "copy", "-oac", "copy", "-of", "lavf", "-o", "out.mp4" ]
try:
pMerge = subprocess.Popen(mp4merge, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
while pMerge.poll() == None:
for l in pMerge.stderr.readlines():
print l
if pMerge.poll() is not None:
print "Complete"
except subprocess.CalledProcessError:
print "fail"
E não funciona, apenas pendura indefinidamente. No entanto, quando executo exatamente o mesmo comando através do Terminal (OS X 10.6.4), ele funciona. O comando é:
mencoder in1.mp4 in2.mp4 -ovc copy -oac copy -of lavf -o out.mp4
Você pode baixar os vídeos daqui. Estou bastante confiante de que os vídeos não são o probelm por causa do fato de que ele funciona no terminal.
Solução
O problema aqui é que pMerge.stderr.readlines()
Bloqueia para sempre até que o processo termine. Ele lê tudo linhas antes de continuar.
Como Mencoder escreve muito no stdout, o buffer de stdout está preenchido e o Mencoder está esperando que ele esvazie antes que possa continuar. Portanto, o processo nunca termina.
Aqui está uma maneira de fazer o mesmo, que não pendura:
pMerge = subprocess.Popen(mp4merge, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = pMerge.communicate()
print stdout
print stderr
Outra opção que permite que você leia a linha por linha é redirecionar o Stderr para Stdout e depois ler apenas o stdout (não use readLines (), pois bloqueia até que todas as linhas sejam lidas):
pMerge = subprocess.Popen(mp4merge, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
for line in pMerge.stdout:
print line,
Isso redireciona o stderr para stdout para que seu buffer não preencha.