在Python例外,如何正确保存状态?

发布于 2025-01-26 14:50:47 字数 906 浏览 1 评论 0原文

我想

  1. 从文件加载数据,
  2. 处理该数据,
  3. 并最终将数据保存回文件。

但是,由于步骤2可能需要几个小时,因此我要确保在出乎意料的例外情况下保存进度。 将数据加载到对象中,以使其易于使用。 我想到的第一件事是将对象类转换为上下文管理器,并使用 statement使用。但是,我几乎必须用陈述在该中写下我的整个程序,但感觉不正确。 所以我环顾四周,发现这个问题本质上要求同一件事。在答案中这个建议 fealref.finalize 对我来说似乎是最有前途的。但是,文档底部有一个注释:

注意:重要的是要确保Func,Args和Kwargs直接或间接对OBJ没有任何参考,因为否则OBJ永远不会被收集。特别是,Func不应是OBJ的约束方法。

由于我想保存该对象的字段,因此我会引用它们,直接陷入此问题。

这是否意味着对象__退出__ - 函数永远不会被调用,或者直到程序崩溃/退出才会被调用?

pythonic的做法是什么?

I want to

  1. load data from files,
  2. work on that data,
  3. and eventually save that data back to files.

However, since step 2 may take several hours I want to make sure that progress is saved in case of an unexpected exception.
The data is loaded into an object to make it easy to work with it.
First thing that came to my mind was to turn that objects class into a context manager and use the with-statement. However I'd have to write practically my entire program within that with-statement and that doesn't feel right.
So I had a look around and found this question which essentially asks for the same thing. Among the answers this one suggesting weakref.finalize seemed the most promising to me. However, there is a note at the bottom of the documentation that says:

Note: It is important to ensure that func, args and kwargs do not own any references to obj, either directly or indirectly, since otherwise obj will never be garbage collected. In particular, func should not be a bound method of obj.

Since I'd want to save fields of that object, I'd reference them, running right into this problem.

Does this mean that the objects __exit__-function will never be called or that it will not be called until the program crashes/exits?

What is the pythonic way of doing this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不再见 2025-02-02 14:50:47

它有点骇客,您仍然包装代码,但是我通常只是在中包装main()尝试 block。

然后,您可以使用使用pdb.set_trace()来处理,这意味着您获得的任何例外,您的程序都会下降到交互式终端而不是破裂。

之后,您可以手动检查错误,并将任何已处理的数据转储到泡菜或您想做的任何事情中。修复错误后,设置代码以读取泡菜,然后从停止的位置捡起。

It's a little hacky, and you still wrap your code, but I normally just wrap main() in a try except block.

Then you can handle except with a pdb.set_trace(), which means whatever exception you get, your program will drop into an interactive terminal instead of breaking.

After that, you can manually inspect the error and dump any processed data into a pickle or whatever you want to do. Once you fix the bug, setup your code to read the pickle and pick up from where it left off.

秋心╮凉 2025-02-02 14:50:47

在答案之后 casualScience ,我发现,而不是使用pdb.set_trace()在哪里输入点是当前的调用堆栈帧(即 block除外),pdb.post_mortem()将使用当前正在处理的异常作为入口点。因此,要在出乎意料的异常后访问和保存数据,最好使用pdb.post_mortem()进入发生异常发生的堆栈框架。

一个更详细的示例如下:

import pdb


def main():
    inner_var = 'Inner Variable'
    1 / 0


if __name__ == '__main__':
    try:
        outer_var = 'Outer Variable'
        main()
    except Exception as e:
        pdb.post_mortem()

运行SCIPT后,控制台将输入验证后调试,并且PDB命令可用于调试,例如使用GUI调试器。

继续上面的示例:

C:\Users\PiaoYang\anaconda3\python.exe C:\Document\PDBDemo\main.py 
> c:\document\pdbdemo\main.py(6)main()
-> 1 / 0
(Pdb) ll
  4     def main():
  5         inner_var = 'Inner Variable'
  6  ->     1 / 0
(Pdb) inner_var
'Inner Variable'
(Pdb) w
  c:\document\pdbdemo\main.py(12)<module>()
-> main()
> c:\document\pdbdemo\main.py(6)main()
-> 1 / 0
(Pdb) u
> c:\document\pdbdemo\main.py(12)<module>()
-> main()
(Pdb) ll
  1     import pdb
  2     
  3     
  4     def main():
  5         inner_var = 'Inner Variable'
  6         1 / 0
  7     
  8     
  9     if __name__ == '__main__':
 10         try:
 11             outer_var = 'Outer Variable'
 12  >>         main()
 13         except Exception as e:
 14  ->         pdb.post_mortem()
(Pdb) outer_var
'Outer Variable'
(Pdb) w
> c:\document\pdbdemo\main.py(12)<module>()
-> main()
  c:\document\pdbdemo\main.py(6)main()
-> 1 / 0
(Pdb) d
> c:\document\pdbdemo\main.py(6)main()
-> 1 / 0
(Pdb) w
  c:\document\pdbdemo\main.py(12)<module>()
-> main()
> c:\document\pdbdemo\main.py(6)main()
-> 1 / 0
(Pdb) q

进程已结束,退出代码为 0

要找出常用的PDB命令,请参考 https ://realpython.com/python-debugging-pdb/#essential-pdb-commands

Following the answer of CasualScience, I find that instead of using the pdb.set_trace() where the entry point is the current calling stack frame (namely the except block), pdb.post_mortem() will use the exception currently being handled as the entry point. So, to access and save the data after the unexpected exception, it's better to use the pdb.post_mortem() to enter the stack frame where the exception happen.

A more detail example is as follows:

import pdb


def main():
    inner_var = 'Inner Variable'
    1 / 0


if __name__ == '__main__':
    try:
        outer_var = 'Outer Variable'
        main()
    except Exception as e:
        pdb.post_mortem()

After running the scipt, the console will enter the post-mortem debugging, and pdb commands can be used to debug like using the GUI debugger.

Continue the above example:

C:\Users\PiaoYang\anaconda3\python.exe C:\Document\PDBDemo\main.py 
> c:\document\pdbdemo\main.py(6)main()
-> 1 / 0
(Pdb) ll
  4     def main():
  5         inner_var = 'Inner Variable'
  6  ->     1 / 0
(Pdb) inner_var
'Inner Variable'
(Pdb) w
  c:\document\pdbdemo\main.py(12)<module>()
-> main()
> c:\document\pdbdemo\main.py(6)main()
-> 1 / 0
(Pdb) u
> c:\document\pdbdemo\main.py(12)<module>()
-> main()
(Pdb) ll
  1     import pdb
  2     
  3     
  4     def main():
  5         inner_var = 'Inner Variable'
  6         1 / 0
  7     
  8     
  9     if __name__ == '__main__':
 10         try:
 11             outer_var = 'Outer Variable'
 12  >>         main()
 13         except Exception as e:
 14  ->         pdb.post_mortem()
(Pdb) outer_var
'Outer Variable'
(Pdb) w
> c:\document\pdbdemo\main.py(12)<module>()
-> main()
  c:\document\pdbdemo\main.py(6)main()
-> 1 / 0
(Pdb) d
> c:\document\pdbdemo\main.py(6)main()
-> 1 / 0
(Pdb) w
  c:\document\pdbdemo\main.py(12)<module>()
-> main()
> c:\document\pdbdemo\main.py(6)main()
-> 1 / 0
(Pdb) q

进程已结束,退出代码为 0

To find out the commonly used pdb commands, ref to https://realpython.com/python-debugging-pdb/#essential-pdb-commands

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文