保证在流程终止时要求销毁

时间:2018-06-10 09:33:04

标签: python python-3.x operating-system

在阅读了大量有关该主题的数据后,我仍然无法找到解决问题的任何实际方法(可能没有)。

我的问题如下:

在我的项目中,我有多个驱动程序使用各种硬件(IO管理器,可编程负载,电源等)。

初始化与这些硬件的连接成本很高(及时),我无法打开然后关闭我们之间每次通信迭代的连接。

含义我不能这样做(假设可编程加载实现进入/退出):

start of code...

with programmable_load(args) as program_instance:
     programmable_load_instance.do_something()

rest of code...

所以我选择了另一种解决方案:

class programmable_load():
    def __init__(self):
         self.handler = handler_creator()
    def close_connection(self):
         self.handler.close_connection()
         self.handler = None
    def __del__(self):
         if (self.handler != None):
             self.close_connection()

由于显而易见的原因,我不“信任”析构函数实际被调用,因此当我想结束我的程序时(对于所有驱动程序),我明确地调用close_connection()。

当我突然终止进程时会出现问题,例如当我通过调试模式运行并退出调试时。

在这些情况下,进程终止而不运行任何析构函数。 我知道操作系统会清除此时未使用的所有内存,但有没有办法以有条理的方式清除内存?

如果没有,有没有办法让退出调试功能通过一组特定的功能? python进程是否知道它有一个非常好的调试事件,还是将它视为正常终止?

操作系统:Windows

3 个答案:

答案 0 :(得分:2)

正如评论中提到的,您可以使用atexit进行清理。但这只有在要求关闭进程时才有效(例如Linux上的QUIT信号)而不仅仅是被杀死(在停止调试会话时可能就是这种情况)。类似地,如果您强制关闭计算机(例如长按电源按钮或断电),那么它也不会被调用。没有'解决方案'由于显而易见的原因。当电源突然断电或被强行杀死时,您的程序无法被调用。强力杀戮的目的是肯定会杀死这个过程。如果它首先调用你的清理代码,那么你可以推迟那个失败的目的。这就是为什么有信号要求你的过程停止。这不是Python特有的。相同的概念也适用于各种操作系统。

奖金(设计建议,而不是解决方案):我认为您仍然可以使用上下文管理器(使用with)。你的问题不是唯一的。数据库连接通常也可以保持更长时间。这是一个范围问题。将上下文进一步移动到应用程序级别。然后很明显边界是什么,你不需要任何魔法(你可能也知道@contextmanager让它变得轻而易举)。

答案 1 :(得分:2)

根据this documentation

  

如果进程被TerminateProcess终止,则所有线程都会被终止   进程立即终止,没有机会再运行   代码。

(强调我的。)这意味着在这种情况下你无能为力。

如详细here所示,ms-windows上的信号效果不佳。

答案 2 :(得分:1)

我没有经过适当的测试,因为这里没有安装wingide,所以我不能授予您这笔费用,但是使用setconsolectrlhandler怎么办?例如,尝试这样的事情:

import os
import sys
import win32api


if __name__ == "__main__":
    def callback(sig, func=None):
        print("Exit handler called!")

    try:
        win32api.SetConsoleCtrlHandler(callback, True)
    except Exception as e:
        print("Captured exception", e)
        sys.exit(1)

    print("Press to quit")
    input()
    print("Bye!")

它将能够处理CTRL+CCTRL+BREAK信号:

enter image description here