Подпроцесс Python + mencoder не работает, та же команда работает в терминале - PullRequest
0 голосов
/ 04 августа 2010

У меня проблема с использованием mencoder (SVN-r30531-4.2.1) через подпроцесс python (2.6.1).Я пытаюсь соединить два файла mp4 одинакового размера, кодека и т. Д. Оба не имеют звука.Код, который я использую для тестирования:

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"

И он не работает, он просто висит бесконечно.Однако, когда я выполняю ту же самую команду через Терминал (OS X 10.6.4), это работает.Команда:

mencoder in1.mp4 in2.mp4 -ovc copy -oac copy -of lavf -o out.mp4

Видео можно загрузить отсюда .Я вполне уверен, что видео не является проблемой из-за того, что оно работает с терминала.

1 Ответ

2 голосов
/ 04 августа 2010

Проблема в том, что pMerge.stderr.readlines() блокируется навсегда, пока процесс не закончится.Перед продолжением он читает все строки.

Поскольку mencoder много пишет в stdout, буфер stdout заполнен, и mencoder ожидает его опустошения, прежде чем продолжить.Таким образом, процесс никогда не заканчивается.

Вот способ сделать то же самое, который не зависнет:

pMerge = subprocess.Popen(mp4merge, stdout=subprocess.PIPE,
    stderr=subprocess.PIPE)
stdout, stderr = pMerge.communicate()
print stdout
print stderr

Еще одна опция, позволяющая читать вывод построчно:перенаправить stderr в stdout, а затем в stdout только для чтения (не используйте readlines (), поскольку он блокируется до тех пор, пока не будут прочитаны все строки):

pMerge = subprocess.Popen(mp4merge, stdout=subprocess.PIPE,
    stderr=subprocess.STDOUT)
for line in pMerge.stdout:
    print line,

Это перенаправляет stderr в stdout, поэтому ваш буфер не будетзаполнить.

...