Python 调用ffmpeg仅在后台终止脚本
我有一个python脚本,它通过子进程调用ffmpeg来执行一些mp3操作。它在前台可以正常工作,但如果我在后台运行它,它会得到ffmpeg命令,而ffmpeg命令本身也会将其配置转储到stderr中。此时,一切都停止,父任务报告为已停止,而不会在任何地方引发异常。我尝试了其他一些简单的命令来代替ffmpeg,它们通常在前台或后台执行 这是问题的最小示例:Python 调用ffmpeg仅在后台终止脚本,python,ffmpeg,subprocess,Python,Ffmpeg,Subprocess,我有一个python脚本,它通过子进程调用ffmpeg来执行一些mp3操作。它在前台可以正常工作,但如果我在后台运行它,它会得到ffmpeg命令,而ffmpeg命令本身也会将其配置转储到stderr中。此时,一切都停止,父任务报告为已停止,而不会在任何地方引发异常。我尝试了其他一些简单的命令来代替ffmpeg,它们通常在前台或后台执行 这是问题的最小示例: import subprocess inf = "3HTOSD.mp3" outf = "out.mp3" args = [ "f
import subprocess
inf = "3HTOSD.mp3"
outf = "out.mp3"
args = [ "ffmpeg",
"-y",
"-i", inf,
"-ss", "0",
"-t", "20",
outf
]
print "About to do"
result = subprocess.call(args)
print "Done"
我真的不明白为什么或者如何包装的进程会导致父进程终止,而至少不会引发错误,也不知道它是如何只在如此特殊的情况下发生的。发生了什么事
此外,我知道ffmpeg并不是最好的软件包,但我正在与使用ffmpeg编译的软件包进行接口,因此再次使用它似乎是明智的。来自python/subprocess/call文档: 等待命令完成,然后返回returncode属性 因此,只要您调用的进程没有退出,您的程序就不会继续 您应该设置一个
Popen
进程对象,将其标准输出和错误放在不同的缓冲区/流中,当出现错误时,终止进程
也许像这样的方法有用:
proc = subprocess.Popen(args, stderr = subprocess.PIPE) # puts stderr into a new stream
while proc.poll() is None:
try:
err = proc.stderr.read()
except: continue
else:
if err:
proc.terminate()
break
例如,它可能与使用parent.py
有关:
from subprocess import check_call
check_call(["python", "-c", "import sys; sys.stdin.readline()"])
如果在bash中作为后台作业运行,则应重现问题:“parent.py脚本显示为stopped”:
$ python parent.py &
[1] 28052
$ jobs
[1]+ Stopped python parent.py
如果是父母
解决方案是重定向输入:
import os
from subprocess import check_call
try:
from subprocess import DEVNULL
except ImportError: # Python 2
DEVNULL = open(os.devnull, 'r+b', 0)
check_call(["python", "-c", "import sys; sys.stdin.readline()"], stdin=DEVNULL)
如果您不需要查看ffmpeg标准输出/标准输出;您还可以将它们重定向到/dev/null
:
check_call(ffmpeg_cmd, stdin=DEVNULL, stdout=DEVNULL, stderr=STDOUT)
我喜欢使用模块。在我看来,它更容易使用
import commands
cmd = "ffmpeg -y -i %s -ss 0 -t 20 %s 2>&1" % (inf, outf)
status, output = commands.getstatusoutput(cmd)
if status != 0:
raise Exception(output)
作为旁注,有时路径可能是一个问题,您可能希望使用ffmpeg二进制文件的绝对路径
matt@goliath:~$ which ffmpeg
/opt/local/bin/ffmpeg
这谢谢你的解释,整个“等待stdin”的事情对我来说是未知的。要实现的最简单的解决方案是将subprocess.PIPE附加到调用的stdin。@TimD:除非在进程运行时读取/写入/关闭相应的管道,否则不要使用PIPE,即不要将其与
subprocess.call()一起使用
函数,即使它碰巧与ffmpeg可执行文件的一些参数集一起工作。您真的读过我的问题吗?你根本没有回答我的问题。