请问Popen等待子进程,即使直接子进程已终止

我正在Windows 8 / XP上使用Python 2.7。


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


p = Popen(["B"], stdout=PIPE, stderr=PIPE)

stdout, stderr = p.communicate()

return

B运行批处理脚本C。C是运行时间较长的脚本,即使C尚未完成,我也希望B退出。我使用以下代码(在B中)完成了此操作:


p = Popen(["C"])

return

当我运行B时,它可以按预期工作。但是,当我运行A时,我希望它在B退出时退出。但是,即使B已经退出,A也会等到C退出。关于正在发生的事情以及可能的解决方案的任何想法?


不幸的是,将A更改为B的明显解决方案不是一种选择。


这是说明此问题的实用示例代码:https : //www.dropbox.com/s/cbplwjpmydogvu2/popen.zip?dl=1


非常感谢任何输入。


慕丝7291255
浏览 370回答 3
3回答

慕容708150

您可以为子流程提供start_new_session模拟C:#!/usr/bin/env pythonimport osimport sysimport platformfrom subprocess import Popen, PIPE# set system/version dependent "start_new_session" analogskwargs = {}if platform.system() == 'Windows':&nbsp; &nbsp; # from msdn [1]&nbsp; &nbsp; CREATE_NEW_PROCESS_GROUP = 0x00000200&nbsp; # note: could get it from subprocess&nbsp; &nbsp; DETACHED_PROCESS = 0x00000008&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # 0x8 | 0x200 == 0x208&nbsp; &nbsp; kwargs.update(creationflags=DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP)&nbsp;&nbsp;elif sys.version_info < (3, 2):&nbsp; # assume posix&nbsp; &nbsp; kwargs.update(preexec_fn=os.setsid)else:&nbsp; # Python 3.2+ and Unix&nbsp; &nbsp; kwargs.update(start_new_session=True)p = Popen(["C"], stdin=PIPE, stdout=PIPE, stderr=PIPE, **kwargs)assert not p.poll()

皈依舞

以下是根据塞巴斯蒂安的答案和此答案改编而成的代码段:#!/usr/bin/env pythonimport osimport sysimport platformfrom subprocess import Popen, PIPE# set system/version dependent "start_new_session" analogskwargs = {}if platform.system() == 'Windows':&nbsp; &nbsp; # from msdn [1]&nbsp; &nbsp; CREATE_NEW_PROCESS_GROUP = 0x00000200&nbsp; # note: could get it from subprocess&nbsp; &nbsp; DETACHED_PROCESS = 0x00000008&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # 0x8 | 0x200 == 0x208&nbsp; &nbsp; kwargs.update(creationflags=DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP, close_fds=True)&nbsp;&nbsp;elif sys.version_info < (3, 2):&nbsp; # assume posix&nbsp; &nbsp; kwargs.update(preexec_fn=os.setsid)else:&nbsp; # Python 3.2+ and Unix&nbsp; &nbsp; kwargs.update(start_new_session=True)p = Popen(["C"], stdin=PIPE, stdout=PIPE, stderr=PIPE, **kwargs)assert not p.poll()我只是在Windows上亲自测试过。

慕的地10843

代码的意图是,std*=DEVNULL即,您不能在此处省略stdin / stdout / stderr(至少在POSIX上-&nbsp;close_fds=True不会在此处关闭std *)。close_fds=True除非您打开了其他(非标准)文件描述符(关闭它们或通过close_fds=True-POSIX上的Python 3的默认值),否则您不需要。在Windows上close_fds=True就足够了(无需重定向),这样子进程就不会继承父进程的文件描述符(在这种情况下,如果您写入stdout或在Windows上一起传递std*=DEVNULL&nbsp;,&nbsp;我还没有测试过会发生什么close_fds=True)。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python