You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在程序退出(含X按钮关闭、退出码-1)时执行函数并保存变量至Pickle?

Fixing atexit Not Triggering on Window Close (Exit Code -1)

Got it, let’s break down why your atexit hook isn’t firing when you click the window’s "X" button, and how to fix it so your variables get saved every time.

The core issue here is that atexit only runs during clean exits—like when you call sys.exit() manually, your script finishes naturally, or you use Ctrl+C (in most cases). But when you click the window close button, your GUI framework (or the OS, for console apps) sends a termination signal that bypasses the normal atexit flow, hence the exit code -1.

Here’s how to handle this scenario for different types of apps:

1. GUI Apps (Tkinter Example)

For Tkinter, you can override the window’s WM_DELETE_WINDOW protocol to intercept the close event, run your save logic, then exit cleanly.

import tkinter as tk
import pickle

# Variables you want to save
user_session = {"username": "piotr_g", "preferences": {"auto_save": True}}

def save_to_pickle():
    """Save variables to a pickle file"""
    print("Saving session data...")
    with open("session_data.pkl", "wb") as f:
        pickle.dump(user_session, f)

def handle_window_close():
    # Run save logic first
    save_to_pickle()
    # Close the app properly (this will trigger any atexit hooks too, if you still have them)
    root.destroy()

# Set up the Tkinter window
root = tk.Tk()
root.title("My App")

# Override the default close behavior
root.protocol("WM_DELETE_WINDOW", handle_window_close)

# Add sample GUI content
tk.Label(root, text="Click the 'X' to close and save data").pack(pady=20)

root.mainloop()

2. GUI Apps (PyQt/PySide Example)

For PyQt/PySide, reimplement the closeEvent method of your main window to catch the close event:

from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel
import sys
import pickle

# Variables to persist
app_state = {"last_opened_file": "report.txt", "window_size": (800, 600)}

def save_state():
    print("Saving app state...")
    with open("app_state.pkl", "wb") as f:
        pickle.dump(app_state, f)

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("PyQt App")
        self.setCentralWidget(QLabel("Close the window to save state"))

    def closeEvent(self, event):
        # Execute save logic before exiting
        save_state()
        # Allow the window to close
        event.accept()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

3. Console Apps (Closing Terminal Window)

If you’re dealing with a console app and the user closes the terminal window (instead of using Ctrl+C), you can catch the SIGTERM signal (sent by the OS in this case) to run your save code:

import atexit
import pickle
import signal
import sys

# Data to save
counter_data = {"total_runs": 15, "last_run": "2024-05-20"}

def save_counter():
    print("Saving counter data...")
    with open("counter.pkl", "wb") as f:
        pickle.dump(counter_data, f)

# Register atexit for clean exits (still useful!)
atexit.register(save_counter)

def handle_termination(signum, frame):
    # Run save logic when SIGTERM/SIGINT is received
    save_counter()
    # Exit cleanly
    sys.exit(0)

# Listen for termination signals
signal.signal(signal.SIGTERM, handle_termination)
signal.signal(signal.SIGINT, handle_termination)

# Simulate your app's main loop
print("App running... Close the terminal window or press Ctrl+C to exit.")
try:
    while True:
        # Your app logic here
        pass
except KeyboardInterrupt:
    pass

Important Notes

  • SIGKILL can’t be caught: If the OS force-terminates your process (e.g., via Task Manager on Windows), there’s no way to run save logic—this is unavoidable.
  • Always test: Make sure to verify that your save code runs in all exit scenarios you care about.

内容的提问来源于stack exchange,提问作者Piotr Gołdyś

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:22:31