繁体   English   中英

杀死python ffmpeg子进程会破坏cli输出

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM