如何让python程序在关闭时执行函数

问题描述 投票:0回答:1

我想在我的程序中添加关闭时自动保存功能。我向GPT寻求帮助,它建议使用SIGNAL或win32api来捕获关闭信号,但是两者都只有在使用

Ctrl+C
关闭时才能成功工作。我希望即使程序终端关闭,该功能也能工作。

例如,如果您在关闭电脑前忘记关闭程序,它也可以自动执行保存功能。

这是 GPT 的建议

import signal
from time import sleep
def handle_exit(signum, frame):
# do something
   with open('text.txt','w',encoding='utf-8') as f:
        f.write(f"signal receive:{signum}")
        
signal.signal(signal.SIGINT, handle_exit)
signal.signal(signal.SIGTERM, handle_exit)
    
while 1:
    sleep(1)

我测试了程序,当我直接关闭程序窗口时,它不会写入文件。

python windows powershell cmd windows-terminal
1个回答
0
投票

在 Windows 中,当您关闭终端窗口时,进程不会收到常见信号,例如 SIGINT (允许正常关闭)

相反,该进程会被操作系统(Windows)突然终止。这是因为关闭按钮不会向底层进程发送任何终止信号,因此进程会立即被终止,而没有任何机会处理清理任务。如果您依赖信号处理来保存数据或执行清理任务,这会直接影响您的代码。

当用户使用

SIGINT
或通过终止信号关闭程序时,您的代码会侦听
SIGTERM
Ctrl+C
来执行保存操作。

但是,如果您关闭终端窗口或关闭计算机,该进程将在没有发送任何信号的情况下终止,因此您的

handle_exit()
函数不会被触发,并且文件中不会保存任何数据。

你可以使用

import atexit
import win32api
import win32con
from time import sleep

def save_data():
    # do aomwthing
    with open('saved_data.txt', 'w', encoding='utf-8') as f:
        f.write("Data saved on exit.\n")

# (close, logoff, shutdown)
def console_ctrl_handler(event):
    if event in (win32con.CTRL_CLOSE_EVENT, win32con.CTRL_LOGOFF_EVENT, win32con.CTRL_SHUTDOWN_EVENT):
        atexit._run_exitfuncs()
        return True
    return False

# Register the save function to be called on normal program exit
atexit.register(save_data)

win32api.SetConsoleCtrlHandler(console_ctrl_handler, True)

def main():
    try:
        while True:
            sleep(1)  
    except KeyboardInterrupt:
        pass  # Handle Ctrl+C 

if __name__ == "__main__":
    main()

console_ctrl_handler() 函数现在可以处理多个事件:

CTRL_CLOSE_EVENT
CTRL_LOGOFF_EVENT
CTRL_SHUTDOWN_EVENT
。当任何这些事件发生时,它显式调用
atexit._run_exitfuncs()
来运行所有已注册的退出处理程序和
win32api.SetConsoleCtrlHandler
并为控制台事件注册我们的自定义处理程序。 对于 win32 常量,请考虑阅读
win32con
常数

© www.soinside.com 2019 - 2024. All rights reserved.