Python:如何启动完整进程而不是子进程并检索PID

19

我希望:

  1. 从我的进程(myexe.exe arg0)启动一个新的进程(myexe.exe arg1)
  2. 获取这个新进程的 PID(在 Windows 操作系统下)
  3. 当我使用任务管理器的“结束进程树”命令杀死我的第一个实体(myexe.exe arg0)时,我需要保证新的实体(myexe.exe arg1)不会被杀死...

我已经尝试过 subprocess.Popen、os.exec、os.spawn 和 os.system 等方法,但没有成功。

另一种解释这个问题的方式是:如何保护 myexe.exe(arg1),即使有人杀掉了 myexe.exe(arg0)的“进程树”?

编辑:相同的问题(没有答案)在这里

编辑:以下命令不能保证子进程的独立性。

subprocess.Popen(["myexe.exe",arg[1]],creationflags = DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP,close_fds = True)

你有任何已完成的示例代码吗? - sotapme
1
可能是从Python启动完全独立的进程的重复问题。 - jtpereyda
4个回答

14

要在Windows上启动一个能够在父进程退出后继续运行的子进程:

from subprocess import Popen, PIPE

CREATE_NEW_PROCESS_GROUP = 0x00000200
DETACHED_PROCESS = 0x00000008

p = Popen(["myexe.exe", "arg1"], stdin=PIPE, stdout=PIPE, stderr=PIPE,
          creationflags=DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP)
print(p.pid)

Windows进程创建标志位在此处

另外还有一个更通用的版本在这里


1
不错的尝试!但是,当我通过Windows任务管理器的“结束进程树”命令杀死“myexe.exe”(arg0)时,两个myexe.exe都被杀死了!如果我只对“myexe.exe”(arg1)执行相同的命令,则只有该实体会被杀死... - baco
@baco:使用仅结束一个进程的选项,而不是“进程树”。 - jfs
@ J.F. Sebastian:即使没有“close_fds”或双重分支,我也可以杀死myexe.exe... - baco
@baco:我应该在“双重fork”中加上引号。我只是指使用Popen两次(创建子进程、创建孙子进程、退出子进程)。虽然这可能是没有意义的。 - jfs
1
Windows进程创建标志现在也可以作为“subprocess” windows常量使用。 - djvg
显示剩余7条评论

1

我尝试了所有针对Windows 10提出的解决方案,但它们仍将新进程作为原始进程的进程树的一部分打开(直接在主进程下方或通过cmd shell)。对我有效的唯一解决方案是使用cmd.exe的start命令创建一个完全独立的进程/分支:

import subprocess
subprocess.Popen(["cmd.exe", "/C", "start notepad"])

这实际上更容易,因为它不需要与 stdin/out 参数打交道。显然,由于它完全独立,您无法与其通信。但是,您可以使用 psutil 检索其 PID,以便至少监视或关闭它(如果必要):

import psutil
for process in psutil.process_iter():
    if process.name() == 'notepad.exe':
        print(process.pid)

1
我几年前在Windows上做过类似的事情,我的问题是想要终止子进程。我认为您可以使用pid = Popen(["/bin/mycmd", "myarg"]).pid运行子进程,所以我不确定真正的问题是什么,所以我猜测当您终止主进程时会出现问题。如果我没记错,那可能与标志有关。我无法证明它,因为我没有运行Windows。
subprocess.CREATE_NEW_CONSOLE
The new process has a new console, instead of inheriting its parent’s console (the default).

This flag is always set when Popen is created with shell=True.

subprocess.CREATE_NEW_PROCESS_GROUP
A Popen creationflags parameter to specify that a new process group will be created. This flag is necessary for using os.kill() on the subprocess.

This flag is ignored if CREATE_NEW_CONSOLE is specified.

1
所以如果我理解正确,代码应该像这样:

from subprocess import Popen, PIPE
script = "C:\myexe.exe"
param = "-help"
DETACHED_PROCESS = 0x00000008
CREATE_NEW_PROCESS_GROUP = 0x00000200
pid = Popen([script, param], shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE,
            creationflags=DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP)

至少我尝试了这个,并且对我起作用。

为什么 DETACHED_PROCESS = 0x00000008? - pitosalas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接