【问题标题】:Why do two sub-processes stop each other from working?为什么两个子进程会互相阻止工作?
【发布时间】:2019-03-01 15:06:49
【问题描述】:

我在让两个子进程一起运行时遇到问题。

第一个子流程是视频流的转码:

subprocess.Popen("ffmpeg -i input output", shell=True)

我需要它在我的程序后台运行,将视频从我的 IP 摄像机转码为 mjpeg 流。

第二个子进程是 Openalpr 守护进程,它查看 mjpeg 流并返回它在流中看到的汽车牌照。

 subprocess.Popen("alprd -f", shell=True)

这是一段尝试运行两个子进程的 python 测试代码示例:

import subprocess
subprocess.Popen("ffmpeg -i input output", shell=True)
subprocess.Popen("alprd -f", shell=True)

当我这样做时,ffmpeg 转码工作正常,我可以查看转码后的 mjpeg 流,我可以在控制台中看到 ffmpegs 详细输出。但是,alprd 守护进程似乎没有按预期返回任何车牌。事实上,我在控制台窗口中看不到 alprd 的任何输出。

如果我只用一个子进程运行上述代码,它就可以工作,例如

import subprocess
subprocess.Popen("ffmpeg -i input output", shell=True)

工作正常,就像这样:

import subprocess
subprocess.Popen("alprd -f", shell=True)

如果我运行上面的两个工作代码 sn-ps 中的任何一个 - 同时在单独的 linux 终端中运行另一个命令,一切正常。

我显然不了解子流程的某些内容,它们显然相互冲突,但是谁能解释发生了什么以及如何解决问题?

谢谢!

【问题讨论】:

  • @M.Jones:你说“我有问题”,但你没有描述问题。出了什么问题?我怀疑这两个进程相互干扰了标准输入/标准输出或终端的使用,但如果不知道您正在观察什么问题,就很难确定。
  • 感谢 MarLei,但这是一个不同的问题 - 我正在使用 Popen,它是非阻塞的。
  • @DanielPryden:问题在于 ffmpeg 命令运行并在控制台中显示大量输出。 alprd 似乎停止了,我在终端中看不到任何预期的输出。
  • @M.Jones:我不熟悉alprd 工具,但它被描述为“守护进程”这一事实表明,像这样从命令行运行它可能不是得到很好的支持。如果您只是编写一个在后台启动两个程序的 shell 脚本,您会得到相同的结果吗?这两个程序是否曾经从终端读取输入?您是否需要两个程序都将输出写入终端,或者让一个或两个程序将输出写入日志文件是否可以接受?

标签: python subprocess


【解决方案1】:

ffmpegalprd 很可能都在尝试与相同的 stdin/stdout 文件句柄进行交互。为了解决这个问题,为一个或两个子进程创建单独的管道以用作标准输入/标准输出。然后他们可以在不相互干扰的情况下与他们互动。

import subprocess

with open('ffmpeg-output.txt', 'w') as ffmpeg_output:
    ffmpeg = subprocess.Popen(
        ['ffmpeg', '-i', 'input', 'output'],
        stdin=subprocess.PIPE,
        stdout=ffmpeg_output,
        stderr=subprocess.STDOUT)
    # We won't be sending any input into ffmpeg's stdin, so close it.
    ffmpeg.stdin.close()

    # alprd inherits stdin, stdout, and stderr from the current process.
    alprd = subprocess.Popen(['alprd', '-f'])

    # Wait for the subprocesses to finish.
    ffmpeg.wait()
    alprd.wait()

【讨论】:

  • 感谢您的回答,这似乎运行正常。我去做一些测试。是否可以转储 ffmpeg 的输出,而不是将其传递给文本文件?它非常冗长,我认为它很快就会变得难以管理。非常感谢您的帮助 - 非常感谢!
  • 如果你想转储它,你可以使用subprocess.DEVNULL而不是文件对象。
猜你喜欢
  • 1970-01-01
  • 2020-04-20
  • 2018-10-12
  • 2021-08-12
  • 1970-01-01
  • 2021-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多