即使直系孩子已经终止,Popen仍在等待孩子的过程

kha*_*tam 15 python subprocess popen

我在Windows 8/XP上使用Python 2.7.

我有一个程序A使用以下代码运行另一个程序B:

p = Popen(["B"], stdout=PIPE, stderr=PIPE)
stdout, stderr = p.communicate()
return
Run Code Online (Sandbox Code Playgroud)

B运行批处理脚本C. C是一个长时间运行的脚本,我希望B退出,即使C还没有完成.我使用以下代码完成了它(在B中):

p = Popen(["C"])
return
Run Code Online (Sandbox Code Playgroud)

当我运行B时,它按预期工作.然而,当我运行A时,我预计它会在B退出时退出.但是A等到C退出,即使B已经退出了.关于发生了什么以及可能的解决方案的任何想法?

不幸的是,将A改为看起来像B的明显解决方案不是一种选择.

以下是用于说明此问题的功能示例代码:https: //www.dropbox.com/s/cbplwjpmydogvu2/popen.zip?dl = 1

任何输入都非常感谢.

jfs*_*jfs 18

您可以为子流程提供start_new_session模拟C:

#!/usr/bin/env python
import os
import sys
import platform
from subprocess import Popen, PIPE

# set system/version dependent "start_new_session" analogs
kwargs = {}
if platform.system() == 'Windows':
    # from msdn [1]
    CREATE_NEW_PROCESS_GROUP = 0x00000200  # note: could get it from subprocess
    DETACHED_PROCESS = 0x00000008          # 0x8 | 0x200 == 0x208
    kwargs.update(creationflags=DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP)  
elif sys.version_info < (3, 2):  # assume posix
    kwargs.update(preexec_fn=os.setsid)
else:  # Python 3.2+ and Unix
    kwargs.update(start_new_session=True)

p = Popen(["C"], stdin=PIPE, stdout=PIPE, stderr=PIPE, **kwargs)
assert not p.poll()
Run Code Online (Sandbox Code Playgroud)

[1]:CreateProcess()的进程创建标志

  • 请注意,从 Python 3.7 开始,在 Windows 上不再需要设置 `close_fds=True` - 现在这是默认设置,并且与重定向 `stdin`/`stdout`/`stderr` 一起使用。错误跟踪器中的详细信息如下:https://bugs.python.org/issue19764 (2认同)