[英]Killing python ffmpeg subprocess breaks cli output
我正在尝试使用子进程执行系统命令并读取输出。
但是,如果命令花费了10秒钟以上,我想杀死该子进程。
我尝试了几种方法。
我的最后一次尝试是受此帖子启发的: https : //stackoverflow.com/a/3326559/969208
例:
import os
import signal
from subprocess import Popen, PIPE
class Alarm(Exception):
pass
def alarm_handler(signum, frame):
raise Alarm
def pexec(args):
p = Popen(args, stdout=PIPE, stderr=PIPE)
signal.signal(signal.SIGALRM, alarm_handler)
signal.alarm(10)
stdout = stderr = ''
try:
stdout, stderr = p.communicate()
signal.alarm(0)
except Alarm:
try:
os.kill(p.pid, signal.SIGKILL)
except:
pass
return (stdout, stderr)
问题是:程序退出后,cli中不会显示任何字符,直到我按回车键为止。 争取回报不会给我新的界限。
我想这与stdout和stderr管道有关。
我试过冲洗并从管道读取(p.stdout.flush())
我也尝试过使用不同的Popen参数,但可能会错过一些东西。 只是以为我会在这里保持简单。
我正在Debian服务器上运行它。
我在这里想念什么吗?
编辑:
似乎只有在终止正在进行的ffmpeg进程时才如此。 如果ffmpeg进程在10秒之前正常退出,则完全没有问题。
我尝试执行几个不同的命令,这些命令花费的时间超过10秒,其中一个输出打印,一个不输出,以及一个ffmpeg命令检查文件的完整性。
args = ['sleep', '12s'] # Works fine
args = ['ls', '-R', '/var'] # Works fine, prints lots for a long time
args = ['ffmpeg', '-v', '1', '-i', 'large_file.mov','-f', 'null', '-'] # Breaks cli output
我相信ffmpeg使用\\ r打印并在strerr管道上打印所有内容。 这可能是原因吗? 任何想法如何解决?
好。 您的代码在我的Ubuntu服务器上肯定可以正常工作。
(我想这是Debian的近亲或兄弟)
我增加了几行,以便我可以测试您的代码。
import os
import signal
from subprocess import Popen, PIPE
class Alarm(Exception):
pass
def alarm_handler(signum, frame):
raise Alarm
def pexec(args):
p = Popen(args, stdout=PIPE, stderr=PIPE)
signal.signal(signal.SIGALRM, alarm_handler)
signal.alarm(1)
stderr = ''
try:
stdout, stderr = p.communicate()
signal.alarm(0)
except Alarm:
print "Done!"
try:
os.kill(p.pid, signal.SIGKILL)
except:
pass
return (stdout, stderr)
args = ('find', '/', '-name','*')
stdout = pexec(args)
print "----------------------result--------------------------"
print stdout
print "----------------------result--------------------------"
奇迹般有效。
如果此代码在您的服务器上有效,我想问题实际上就在于
您尝试检索数据的命令行应用程序。
我也有同样的问题。 我无法获得运行中的FFmpeg来从python子<process>.kill()
正常终止,因此我正在使用<process>.kill()
。 但是我认为这意味着FFmpeg无法正确还原tty的模式(如此处所述: https : //askubuntu.com/a/172747 )
您可以通过在bash提示符处运行reset
恢复外壳,但这会清除屏幕,因此在继续工作时看不到脚本的输出。
更好的方法是运行stty echo
,以便在您的Shell会话中重新打开stty echo
。
对FFmpeg进行核对后,甚至可以在脚本中运行它。 我在做:
ffmpeg_popen.kill()
ffmpeg_popen.wait()
subprocess.call(["stty", "echo"])
这在bash作为shell的Ubuntu上对我有效。 YMMV,但希望对您有所帮助。 它闻起来很黑,但这是我找到的最好的解决方案。
我遇到了ffmpeg的类似问题。 看来,如果使用Popen.kill()将ffmpeg杀死,则无法正确关闭ffmpeg,也不会恢复终端上的回显。
我们可以使用管道连接到stdin,然后像在cli会话中那样写q来关闭ffmpeg来解决此问题:
p = Popen(args, stdin=PIPE stdout=PIPE, stderr=PIPE)
p.stdin.write(b"q")
最好使用Popen.communicate以避免死锁。 以下内容也将起作用:
p = Popen(args, stdin=PIPE stdout=PIPE, stderr=PIPE)
p.communicate(b'q')
但似乎甚至以下作品:
p = Popen(args, stdin=PIPE stdout=PIPE, stderr=PIPE)
p.kill()
我不确定是什么原因导致该ffmpeg干净关闭,如果它具有输入管道。 也许与最初导致此错误的原因有关?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.