如何在Python3中使用子进程生成字符串输出

时间:2018-05-03 05:20:49

标签: python subprocess

我有一个脚本可以在本地保存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 :(得分:0)

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'。如果文件名是脚本打印的唯一内容,那么提取它就不会太难。

答案 1 :(得分:0)

管道命令时,这是一个常见问题。 IO子系统在终端和文件或管道上处理不同的输出。在终端上,输出在每个换行符上刷新,除非程序明确要求显式刷新,否则不会附加到文件或管道上。

第一个命令在文件末尾结束的管道上不存在问题,因为在命令存在之前刷新所有内容,并关闭管道的写入结束。因此,下一个命令会看到文件结束,一切都会顺利传播。

但是当第一个程序包含无限读取循环时,它会对其输出进行排队,但在缓冲区已满之前不会刷新任何内容,并且缓冲区在现代系统上是巨大的。在这种情况下,一切正常,但你看不到任何输出。

答案 2 :(得分:0)

这是基于Alexandre Cox提议的版本,带有通过管道命令检查安装的命令:

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'