如果 Windows 即将关闭/重新启动/注销/ sleep ,我不想丢失我的设置,是否可以在关闭前保存它?或者是否有另一种方法来保存信息而不用担心它会在 Windows 关闭时丢失? JSON、CSV、数据库?有什么事吗?
s = {1,2,3,4}
with open("s.pick","wb") as f: # pickle it to file when PC about to shutdown to save information
pickle.dump(s,f)
请您参考如下方法:
I do not want to lose my sets if windows is about to shutdown/restart/log off/sleep, Is it possible to save it before shutdown?
是的,如果您构建了一个带有消息循环的应用程序,您可以收到 WM_QUERYENDSESSION 信息。如果你想要一个 GUI,大多数 GUI 库可能会以他们自己的方式包装它。如果不需要 GUI,最简单的解决方案可能是使用 PyWin32 .在文档的某处有一个关于创建隐藏窗口和编写简单消息循环的教程。只需在主线程上执行此操作,然后在后台线程上执行真正的工作,并在 WM_QUERYENDSESSION 时向后台线程发送信号。消息进来了。
或者,更简单地说,正如 Evgeny Prokurat 所建议的那样,只需使用 SetConsoleCtrlHandler (再次通过 PyWin32)。这也可以捕获 ^C、^BREAK 和关闭控制台的用户,以及 WM_QUERYENDSESSION 发出的注销和关机消息。捕获。更重要的是,它不需要消息循环,因此如果您没有任何其他需求,它会简单得多。
Or is there an alternative to save information without worring it will get lost on windows shutdown? JSON, CSV, DB? Anything?
文件格式不会神奇地解决任何问题。但是,数据库可能有两个优势。
首先,您可以通过尽可能多地写作来减少问题。但是对于大多数文件格式,这意味着要尽可能频繁地重写整个文件,这会非常慢。解决方案是流式传输到一个更简单的“日志”文件,减少将其打包到真实文件中的频率,并在每次启动时寻找剩余的日志。您可以手动执行此操作,但数据库通常会自动为您执行此操作。
其次,如果您在写入过程中被杀死,您将得到半个文件。您可以通过原子写入技巧来解决这个问题——编写一个临时文件,然后用临时文件替换旧文件——但这在 Windows 上很难做到正确(尤其是使用 Python 2.x)(参见 Getting atomic writes right ),然后再重复一遍,数据库通常会为您完成。
执行此操作的“正确”方法是创建一个新的窗口类,其中包含一个在 WM_QUERYENDSESSION 上分派(dispatch)给您的处理程序的 msgproc .正如 MFC 使这比原始 Win32 API 代码更容易一样,win32ui (包装 MFC)使这比 win32api 更容易/win32gui (它包装了原始的 Win32 API)。您可以找到很多示例(例如,快速搜索“pywin32 msgproc 示例”会找到类似 this 的示例,搜索“python win32ui”和类似的术语也同样有效)。
但是,在这种情况下,您没有想要像普通窗口一样工作的窗口,因此直接进入低级别并编写快速且肮脏的消息循环可能更容易。不幸的是,要找到示例代码要困难得多——您基本上必须在 native 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。 ,因为这些部分有更多(也更容易找到)好的样本;这是很难找到的部分。
