为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕丝7291255 2019-11-03 11:04:20
我正在Windows 8 / XP上使用Python 2.7。我有一个程序A,它使用以下代码运行另一个程序B:p = Popen(["B"], stdout=PIPE, stderr=PIPE)stdout, stderr = p.communicate()returnB运行批处理脚本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非常感谢任何输入。
查看完整描述

3 回答

?
慕容708150

TA贡献1831条经验 获得超4个赞

您可以为子流程提供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()



查看完整回答
反对 回复 2019-11-04
?
皈依舞

TA贡献1851条经验 获得超3个赞

以下是根据塞巴斯蒂安的答案和此答案改编而成的代码段:


#!/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, close_fds=True)  

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()

我只是在Windows上亲自测试过。



查看完整回答
反对 回复 2019-11-04
?
慕的地10843

TA贡献1785条经验 获得超8个赞

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


查看完整回答
反对 回复 2019-11-04
  • 3 回答
  • 0 关注
  • 369 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信