如果windows即将关机/重启/注销/休眠,我不想丢失我的设置,是否可以在关机前保存?
是的,如果您构建了一个带有消息循环的应用,您可以收到WM_QUERYENDSESSION 消息。如果您想拥有一个 GUI,大多数 GUI 库可能会以自己的方式将其包装起来。如果您不需要 GUI,您最简单的解决方案可能是使用PyWin32。在文档的某处,有一个关于创建隐藏窗口和编写简单消息循环的教程。只需在主线程上执行此操作,然后在后台线程上执行真正的工作,并在收到WM_QUERYENDSESSION 消息时向您的后台线程发出信号。
或者,更简单的是,正如 Evgeny Prokurat 建议的那样,只需使用 SetConsoleCtrlHandler(再次通过 PyWin32)。这也可以捕获 ^C、^BREAK 和关闭控制台的用户,以及 WM_QUERYENDSESSION 捕获的注销和关闭消息。更重要的是,它不需要消息循环,所以如果您没有其他需要,它会简单得多。
或者是否有其他方法可以保存信息而不用担心它会在 Windows 关闭时丢失? JSON、CSV、数据库?有什么事吗?
文件格式不会神奇地解决任何问题。但是,数据库可能有两个优点。
首先,您可以通过尽可能多地写作来减少问题。但是对于大多数文件格式,这意味着尽可能频繁地重写整个文件,这将非常慢。解决方案是流式传输到一个更简单的“日志”文件,减少将其打包到真实文件中的频率,并在每次启动时寻找剩余的日志。您可以手动执行此操作,但数据库通常会自动为您执行此操作。
其次,如果你在写入过程中被杀死,你最终会得到半个文件。你可以通过原子写入技巧来解决这个问题——编写一个临时文件,然后用临时文件替换旧文件——但这在 Windows 上很难做到(尤其是 Python 2.x)(参见Getting atomic writes right),然后再一次,数据库通常会为您完成。
执行此操作的“正确”方法是创建一个带有 msgproc 的新窗口类,该类将分派到WM_QUERYENDSESSION 上的处理程序。正如 MFC 使这比原始 Win32 API 代码更容易,win32ui(包装 MFC)比 win32api/win32gui(包装原始 Win32 API)更容易。您可以找到很多相关示例(例如,快速搜索“pywin32 msgproc 示例”会找到像 this 这样的示例,搜索“python win32ui”和类似术语也同样有效)。
但是,在这种情况下,您没有想要像普通窗口一样操作的窗口,因此直接进入低级别并编写一个快速而肮脏的消息循环可能会更容易。不幸的是,要找到示例代码要困难得多——您基本上必须在本机 API 中搜索 C 示例代码(例如 MSDN 上的 Creating a Message Loop),然后通过 pywin32 文档弄清楚如何将其转换为 Python。不太理想,特别是如果您不了解 C,但也没有那么那么难。下面是一个帮助您入门的示例:
def msgloop():
while True:
msg = win32gui.GetMessage(None, 0, 0)
if msg and msg.message == win32con.WM_QUERYENDSESSION:
handle_shutdown()
win32api.TranslateMessage(msg)
win32api.DispatchMessage(msg)
if msg and msg.message == win32con.WM_QUIT:
return msg.wparam
worker = threading.Thread(real_program)
worker.start()
exitcode = msgloop()
worker.join()
sys.exit(exitcode)
我没有展示“如何创建最小的隐藏窗口”部分,或者如何向工作人员发出停止的信号,例如 threading.Condition,因为还有更多(而且更容易找到) ) 这些零件的良好样品;这是很难找到的部分。