Как сгенерировать вывод строки с подпроцессом в Python3 - PullRequest
0 голосов
/ 03 мая 2018

У меня есть скрипт, который локально сохраняет видео продолжительностью 5 секунд и в нем не указывается имя файла.

Вот команда bash

ffmpeg -i http://0.0.0.0:8080/stream/video.mjpeg -vcodec copy -map 0 -f segment -segment_time 2 -loglevel 40 -segment_format mp4 capture-%05d.mp4 2>&1 | grep --line-buffered -Eo "segment:.+ended" | gawk -F "'" '{print $2; system("")}' | xargs -n1 

Если я выполню эту команду в терминале, она вернет ожидаемое имя файла, как таковое

capture-00001.mp4

Обратите внимание, что команда xargs в конце легко позволяет мне передать имя файла скрипту Python в качестве нового аргумента. Но теперь я хочу выполнить эту команду внутри самого Python, а именно получить имя файла с subprocess.

Вот что я сделал до сих пор. При запуске сценария, как и ожидалось, терминал напечатает имя файла, но никогда не передаст его в виде строки в fName. Я пробовал subprocess.check_output, но он никогда ничего не пропускает, так как команда непрерывно записывает видео и сохраняет его локально.

FFMPEG_SCRIPT = r"""ffmpeg -i http://0.0.0.0:8080/stream/video.mjpeg -vcodec copy -map 0 -f segment -segment_time 2 -loglevel 40 -segment_format mp4 capture-%05d.mp4 2>&1 | grep --line-buffered -Eo "segment:.+ended" | gawk -F "'" '{print $2; system("")}' | xargs -n1 """

try:
    fName = subprocess.check_call(FFMPEG_SCRIPT, stderr=subprocess.STDOUT, shell=True).decode('utf-8')
    print(">>> {}".format(fName))
except subprocess.CalledProcessError as e:
    print(e.output)

Ответы [ 3 ]

0 голосов
/ 03 мая 2018

Это распространенная проблема, когда вы передаете команды. Подсистема ввода-вывода по-разному обрабатывает вывод на терминале и в файлах или каналах. На терминале вывод сбрасывается на каждой новой строке, которая не добавляется в файлы или каналы, если только программа специально не запрашивает явный сброс.

Это не проблема для конвейеров, где первая команда заканчивается в конце файла, потому что все сбрасывается до того, как команда существует, и конец записи канала закрывается. Поэтому следующие команды видят конец файла и все распространяется гладко.

Но когда первая программа содержит бесконечный цикл чтения, она ставит свои выходные данные в очередь, но ничего не сбрасывается до тех пор, пока буфер не заполнится, а в современных системах буфера огромны. В этом случае все работает нормально, но вы не можете видеть вывод.

0 голосов
/ 16 июня 2019

Вот версия, основанная на предложении Александра Кокса с конвейерной командой для проверки монтирования:

import subprocess

fName = subprocess.Popen('mount | grep sda3 | cut -d " " -f 3', shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
(stdout, stderr) = fName.communicate()
print(">>> {}".format(fName))
print(stdout)

Если монтирование существует, вывод:

>>> <subprocess.Popen object at 0x7f9b5eb2fdd8>
b'/mnt/sda3\n'
0 голосов
/ 03 мая 2018
import subprocess
from subprocess import PIPE

fName = subprocess.Popen("test.bat", stdin=PIPE, stdout=PIPE)
(stdout, stderr) = fName.communicate()
print(">>> {}".format(fName))
print(stdout)

test.bat - это простой echo yes, так как я не могу протестировать ваш скрипт, и в результате вывод print(stdout) равен b'yes\r\n'. Если имя файла - единственное, что печатает сценарий, его не должно быть слишком сложно извлечь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...