32

我正在尝试从 python 启动一个完全独立的进程。我不能使用像 os.startfile 这样简单的东西,因为我需要传递参数。目前我正在使用 subprocess.popen ,它可以让我完成 90% 的工作。

args = ["some_exe.exe", "some_arg", "another_arg"]
subprocess.Popen(args, creationflags=DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)

将 popen 与 std* 的分离创建标志和管道一起使用确实会启动一个新进程,该进程在父进程死亡后仍然存在。所以这一切都很好。问题是新的“子”进程仍然持有父进程的虚拟句柄。因此,如果我尝试卸载父 exe(我的 python 脚本通过 pyinstaller 捆绑到一个 exe 中),msiexec 会抱怨父 exe 仍在使用中。

所以目标是产生一个完全独立的进程来运行“some_exe.exe”,它没有任何句柄回到原始进程。

注意:这适用于 Windows XP 及更高版本。我正在Win7上开发。

4

2 回答 2

27

我想我找到了答案。通过使用Popenwith,close_fds = True我能够启动一个独立且没有父句柄的进程。

对于文档,请查看此处并搜索close_fds.

或者,在 Windows 上,如果 close_fds 为真,则子进程将不会继承任何句柄。请注意,在 Windows 上,您不能将 close_fds 设置为 true,也不能通过设置 stdin、stdout 或 stderr 来重定向标准句柄。

请注意,此解决方案仅适用于 Windows。我不知道任何 *nix 系统。

于 2012-11-27T21:46:54.347 回答
4

我在这里找到了这个:

在 windows (win xp) 上,父进程在 longtask.py 完成工作之前不会完成。这不是您在 CGI 脚本中想要的。该问题并非特定于 Python,在 PHP 社区中的问题是相同的。

解决方法是把 DETACHED_PROCESS进程创建标志传递给 win API 中底层的CreateProcess函数。如果你碰巧安装了 pywin32,你可以从 win32process 模块导入标志,否则你应该自己定义它:

DETACHED_PROCESS = 0x00000008

pid = subprocess.Popen([sys.executable, "longtask.py"], creationflags=DETACHED_PROCESS).pid

于 2012-11-27T21:24:04.707 回答