从 Node 中杀死 Python 进程并不会杀死 Python 的子进程(子进程是 ffmpeg.exe)

僵局

我正在开发一个电子应用程序。在这个应用程序中,我使用文件路径作为参数生成一个 Python 进程,然后将文件本身传递给 ffmpeg(通过 ffmpeg-python 模块),然后通过一些 Tensorflow 函数。

我正在尝试处理用户在整个后台进程进行时关闭 Electron 应用程序的情况。不过,从我的测试来看,ffmpeg 的进程似乎无论如何都保持不变。我在 Windows 上,我正在查看任务管理器,但我不确定发生了什么:关闭 Electron 应用程序的窗口时,有时 ffmpeg.exe 将是一个进程,有时它会留在 Electron进程组。

我注意到,如果我通过关闭窗口来杀死 Electron 的进程,那么一旦 ffmpeg 完成它的工作,python 进程也会关闭,所以我想这是一半的工作。问题是,ffmpeg 正在做密集的工作,如果用户需要关闭窗口,那么 ffmpeg 进程也需要被杀死。但我无法以任何方式实现这一目标。

我已经尝试了几件事,所以我将粘贴一些代码:

main.js

// retrieve video data
ipcMain.handle('get-games', async (event, arg) => {
    const spawn = require('child_process').spawn;
    const pythonProcess = spawn('python', ["./backend/predict_games.py", arg]);

    // sets pythonProcess as a global variable to be accessed when quitting the app
    global.childProcess = pythonProcess;

    return new Promise((resolve, reject) => {
        let result = "";

        pythonProcess.stdout.on('data', async (data) => {
            data = String(data);

            if (data.startsWith("{"))
                result = JSON.parse(data);
        });

        pythonProcess.on('close', () => {
            resolve(result);
        })

        pythonProcess.on('error', (err) => {
            reject(err);
        });
    })
});

app.on('before-quit', function () {
    global.childProcess.kill('SIGINT');
});

predict_games.py(ffmpeg 部分)

def convert_video_to_frames(fps, input_file):
    # a few useful directories
    local_dir = os.path.dirname(os.path.abspath(__file__))
    snapshots_dir = fr"{local_dir}/snapshots/{input_file.stem}"

    # creates snapshots folder if it doesn't exist
    Path(snapshots_dir).mkdir(parents=True, exist_ok=True)

print(f"Processing: {Path(fr'{input_file}')}")
try:
    (
        ffmpeg.input(Path(input_file))
        .filter("fps", fps=fps)
        .output(f"{snapshots_dir}/%d.jpg", s="426x240", start_number=0)
        .run(capture_stdout=True, capture_stderr=True)
    )
except ffmpeg.Error as e:
    print("stdout:", e.stdout.decode("utf8"))
    print("stderr:", e.stderr.decode("utf8"))

有没有人有任何线索?

僵局

好吧,我终于能够解决这个问题了!由于 ffmpeg-python 只是旧 ffmpeg 的绑定集合,可执行文件本身仍然是模块的核心。这也意味着,当 ffmpeg 运行时,会出现类似这样的屏幕:

... 

    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
  Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 159 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
Stream mapping:
  Stream #0:0 (h264) -> fps:default
  fps:default -> Stream #0:0 (mjpeg)

...

Press [q] to stop, [?] for help

是幕后发生的事情。一旦我意识到这一点,我所要做的就是找到一种方法将“q”发送到 ffmpeg 的标准输入。我通过在window-all-closed事件中添加这个片段来做到这一点:

app.on('window-all-closed', () => {
    // writes a 'q' in ffmpeg's terminal to quit ffmpeg's process
    // reminder: python gets closed when the Electron app is closed
    global.childProcess.stdin.write("q\n");

    if (process.platform !== 'darwin') app.quit()
})

与问题中的代码段相比,Python 脚本本身没有受到影响,这是我最终修改的唯一内容。现在每次我退出我的 Electron 应用程序时,ffmpeg 都会收到一个“q”。Python 进程不需要手动终止,因为 Electron 已经为您完成了。

所以问题解决了。:)

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

python 杀死python的子进程

来自分类Linux

在python中杀死sudo启动的子进程

来自分类Dev

无法从 python 中杀死 robocopy 子进程

来自分类Dev

Python子进程杀死超时

来自分类Dev

Ctrl C不会杀死Python中循环的子进程

来自分类Dev

python subprocess.Popen使用子进程杀死进程

来自分类Linux

如何干净地杀死python中的子进程

来自分类Dev

杀死在Python的__init__类中创建的子进程

来自分类Dev

在python子进程中退出无限进程

来自分类Python

如果父项在Python中被杀死,则杀死子进程

来自分类Dev

如何不杀死另一个进程在python中打开的子进程?

来自分类Dev

在Python中打开ffmpeg子进程时出错

来自分类Dev

Python ffmpeg子进程:管道损坏

来自分类Dev

使用Python子进程冻结到FFMPEG

来自分类Dev

Windows中的Python子进程

来自分类Dev

python中的子进程终止

来自分类Dev

python中的子进程模块

来自分类Dev

Python中的子进程超时

来自分类Dev

当在OS X上杀死Python进程时,为什么不杀死子进程呢?

来自分类Dev

从Node JS子进程中的python脚本返回结果

来自分类Dev

python子进程-分离进程

来自分类Linux

Python:当父母去世时,如何杀死子进程?

来自分类Dev

Node.js 子进程到 Python 进程

来自分类Dev

Python多处理:如果父进程被杀死,子进程会挂起吗?

来自分类Dev

如何在python中杀死一个分叉的孩子及其Jackd子进程

来自分类Dev

如何在python中杀死一个子进程

来自分类Dev

Python子进程权限

来自分类Dev

python子进程:FileNotFoundError

来自分类Dev

在python子进程中为后台进程使用'&'