Python 更改进程状态

36 阅读3分钟

用户想要在 Python 中搜索并显示一个进程,例如 emacs。他们使用 p = subprocess.Popen('ps -A | grep emacs',shell=True,stdout=subprocess.PIPE) 来获取进程。接下来,他们想知道如何唤醒它并显示它。换句话说,问题是:如何使用 Python 更改进程的状态?

2. 解决方案

答案1:

简而言之,Python 有一个 pty 模块,您可以在其中找到解决方案。这个问题看起来并不简单。通过传递相应的信号可以轻松更改进程的运行状态,但操作前台/后台属性并不容易。当我们谈论操作前台/后台进程时,我们实际上是在谈论“作业控制”。在 UNIX 环境中,作业控制是通过协调多个部分来实现的,包括内核、控制终端、当前 shell 和在该 shell 会话中调用的几乎所有进程。要让进程返回前台,您必须同时告诉其他进程保持沉默并转到后台。看到了吗?

让我们回到你的问题。这个问题可能有两种答案,一种是不可能,另一种是可能但如何实现。

为什么会有两种答案?

通常,除非您为其编程,否则您无法进行作业控制。您也无法使用简单的管道来实现协调模型,从而导致作业控制机制;原因很重要,因为您无法通过管道传递信号。这就是答案是不可能的,至少在简单的管道实现中不可能。

但是,如果您有足够的耐心来对终端 I/O 进行编程,那么仍然可以花费大量工作来完成。概念很简单:您欺骗您的从属程序(在本例中为 emacs),使其认为它已经连接到一个真实终端,该终端具有真正的键盘和固定的显示器备用,并且您准备让您的主程序(即 Python 脚本)处理并中继从其控制终端到从属伪终端的必要事件。

许多终端仿真器实际上采用了这种模式。在您的案例中,您只需要编写另一个终端仿真器……等等!是否始终必须付出如此多的努力?

幸运的是,没有。

在交互式场景中,您的 shell 会为您管理所有内容。你只需告诉 shell“fg/bg”任务,在现实生活中相当容易。可以在 shell 的手册页中找到指定的命令组合。它可能看起来像“jobs -l | grep emacs”以及“fg %1”。然而,这些组合命令不能由程序调用。这是一个不同的故事,因为程序将启动一个新的 shell 来解释其命令,而这样一个新的 shell 无法控制正在运行的旧 emacs,因为它没有特权。用键盘键入它并在显示器上读出它;这是一个交互式场景。

在自动化场景中,在采用作业控制设计之前三思而后行,因为大多数自动化场景不需要作业控制模式。您需要一个编辑器这里和一个播放器那里,这很好,但千万不要让他们保持“后台”状态并弹出到“前台”。最好在它们完成任务后退出。

但如果您不幸地在自动化程序中对作业控制进行编程,请尝试对伪终端主机和从属 I/O 进行编程。它们看起来像一个复杂的 IPC 机制,它们的详细信息取决于操作系统。不过,这是您问题的标准答案;我知道虽然令人讨厌。