【问题标题】:Python Save Sets To File On Windows Shutdown?在 Windows 关闭时,Python 保存集到文件?
【发布时间】:2014-08-03 11:16:04
【问题描述】:

如果windows即将关机/重启/注销/睡眠,我不想丢失我的设置,是否可以在关机前保存它?或者是否有另一种方法可以保存信息而不用担心它会在 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)

【问题讨论】:

  • 使用pickle有什么问题?
  • 保存这些数据有多重要?如果机器挂起或突然断电会怎样?
  • @user2357112:好点。设计为首先处理任意终止,然后添加利用关闭消息传递的代码来更好地处理这种情况。
  • @abarnert 可以处理任意终止吗?如果我有在 try catch 的 for 循环中运行的函数(在 expetion 中我会用 open 做什么?)这会起作用吗?\
  • @IlanTiger:有些情况您可能无法检测和处理,例如有人拉电源或 CPU 着火。因此,您需要设计您的代码,以便无论它如何关闭,您都能够恢复。基本思想是在没有某种具有原子提交的事务的情况下永远不要修改任何关键的外部数据。这可能仅意味着单个文件的 atomic-write-temp-and-replace 或数据库的 begin transaction,或者可能意味着各种日志来跟踪文件或分布式系统之间的依赖关系,具体取决于您的应用程序。

标签: python python-2.7 shutdown power-management


【解决方案1】:

您可以使用win32api.setConsoleCtrlHandler 检测 Windows 关闭/注销

有一个很好的例子How To Catch “Kill” Events with Python

【讨论】:

  • 很好,我完全忘记了。
  • @Evgeny 遗憾的是,这只有在您使用 python.exe 在控制台上运行脚本时才能正常工作,但如果您使用 pythonw.exe 在后台运行它则不行。
  • @BorisDaka:那就不要在后台运行了;使用隐藏的控制台运行它。如果您真的想要pythonw,您可以创建一个隐藏的用户窗口并使用我的答案中的其他机制。
【解决方案2】:

如果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,因为还有更多(而且更容易找到) ) 这些零件的良好样品;这是很难找到的部分。

【讨论】:

  • 我认为隐藏控制台的指南将非常有用,有任何链接吗?我已经尝试寻找它SetConsoleCtrlHandler 还需要一个隐藏的控制台窗口才能工作
  • @BorisDaka:当一个普通的.py文件被双击时,它会得到一个控制台来运行它;当用户从命令行运行.py 文件时,它会继承命令行的控制台;等等。只有当您使用.pyw 文件时,您才会获得控制台——但使用.pyw 文件的唯一原因是您想要一个 GUI,在这种情况下您可以使用其他机制.
  • 我正在使用 cx-freeze windows .exe 文件,这有什么不同吗?
  • @BorisDaka:我很确定cx_Freeze 可用于控制台和 GUI 应用程序。我不记得您是否必须在安装文件中做任何不同的事情,或者它是否仅取决于您的主脚本是.py 还是.pyw,但无论哪种方式,您都应该能够弄清楚哪个您正在构建并为该案例做适当的事情(或切换到另一个案例,如果您发现它不是您想要的)。
  • @abarnert 嘿,当控制台应用程序 SetConsoleCtrlHandler 运行良好时,我已经进行了研究和测试,但是当它是 gui 时,情况并非如此(是的,有退出的 GUI 功能)但我需要在GUI,我不显示控制台。有没有办法在那种情况下我应该使用 WM_QUERYENDSESSION 你有那个页面,他们显示那个例子我没有成功重建它
猜你喜欢
  • 2016-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-16
  • 2012-06-25
相关资源
最近更新 更多