Python-Windows-“不相关"时退出子进程父母死亡/崩溃 [英] Python - Windows - Exiting Child Process when "unrelated" parent dies/crashes

查看:26
本文介绍了Python-Windows-“不相关"时退出子进程父母死亡/崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

经过一些研究,对于如何让子进程了解父进程在 Windows 下已死亡/崩溃/退出这可以使子进程无人看管的运行,没有明确的答案.有一些建议如下:

After some research there was no definitive answer as to how to have a child process understand that the parent process has died/crashed/exited under Windows which can make the child process run unattended. There are some proposals as in:

Psutil:子进程:删除 Windows 中的子进程

多处理:如果父进程是,则杀死子进程在 Python 中被杀死

总是涉及已经开始孩子的已知父母.但也有孩子不知道自己是孩子的情况,因为他不是被认为是孩子,父母也没有试图杀死孩子.

Always involving a known parent which has started a child. But there are cases in which the child doesn't know it is a child, because it is not conceived as a child and the parent makes no effort to kill the children.

此外,没有对父级的控制.实际案例:

Furthermore, there is no control of the parent. Practical case:

  • 在 Windows 下运行的 Cygwin
  • Windows Python 路径中的第 1 个
  • 通过 setuptools entry_points 工具安装的 Python 可执行文件.
  • Cygwin running under Windows
  • Windows Python 1st in the path
  • Python executable installed via setuptools entry_points facility.

如上所述,要执行的 Python 是 Windows 的.setuptools 生成的可执行文件将找到它并将其作为带有关联脚本的子进程执行.

As mentioned above the Python to be executed is the Windows one. The setuptools-generated executable will find it and execute it as subprocess with the asocciated script.

因为在 Cygwin 下运行,以下可能会失败:

Because one is running under Cygwin the following may fail:

  • Ctrl-c 将杀死父级(存根 setuptools 可执行文件)
  • 但是会让子进程继续运行(在进程列表中可以找到 python.exe)
  • Pressing Ctrl-c will kill the parent (the stub setuptools executable)
  • But will leave the child running (to be found in the process list as python.exe)

在这种情况下,如上所述,无法控制父级,而子级不知道它是子级(因为它也可以作为 Python 脚本直接执行)

In this case and as mentioned above, it isn't possible to control the parent and the child doesn't know it's a child (because it may also be directly executed as a Python script)

推荐答案

解决方法如下

import sys

def win_wait_for_parent(raise_exceptions=False):
    if not sys.platform == 'win32':
        return True

    # When started under cygwin, the parent process will die leaving a child
    # hanging around. The process has to be waited upon
    import ctypes
    from ctypes.wintypes import DWORD, BOOL, HANDLE
    import os
    import threading

    INFINITE = -1
    SYNCHRONIZE = 0x00100000

    kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)

    kernel32.OpenProcess.argtypes = (DWORD, BOOL, DWORD)
    kernel32.OpenProcess.restype = HANDLE

    kernel32.WaitForSingleObject.argtypes = (HANDLE, DWORD)
    kernel32.WaitForSingleObject.restype = DWORD

    phandle = kernel32.OpenProcess(SYNCHRONIZE, 0, os.getppid())

    def check_parent():
        # Get a token with right access to parent and wait for it to be
        # signaled (die). Exit ourselves then
            kernel32.WaitForSingleObject(phandle, INFINITE)
            os._exit(0)

    if not phandle:
        if raise_exceptions:
            raise ctypes.WinError(ctypes.get_last_error())

        return False

    threading.Thread(target=check_parent).start()
    return True

如果进程的 PID 与等待父进程收到信号(死亡)的父进程的 PID 不同,则它在单独的线程中运行.这适用于 Python 3.3,其中 os.getppid() 实际上返回窗口下父级的 PID

which runs in a separate thread if the PID of the process is not the same as the PID of the parent waiting for the parent to be signaled (death). This works under Python 3.3, where os.getppid() does actually returnt the PID of the parent under window

它不需要修改父进程,子进程也不需要像子进程一样提前编码,因为会检查线程必须在哪里运行.

It requires no modification of the parent and the child doesn't need to be coded in advance as a child, because a check is done as to where the thread has to run or no.

-- 重构为函数并从评论中添加改进

-- refactored as a function and added improvements from comments

这篇关于Python-Windows-“不相关"时退出子进程父母死亡/崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆