我想在我的程序中添加关闭时自动保存功能。我向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)
我测试了程序,当我直接关闭程序窗口时,它不会写入文件。
在 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
常数