Python中出现异常时如何正确保存状态?

问题描述 投票:0回答:2

我想要

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

但是,由于第 2 步可能需要几个小时,我想确保在出现意外异常时保存进度。 数据被加载到对象中以便于使用它。 我想到的第一件事是将对象类转换为上下文管理器并使用

with
语句。然而,我实际上必须在该
with
语句中编写我的整个程序,这感觉不对。 所以我环顾四周,发现“这个问题”本质上要求同样的事情。在答案中,“这个”建议“weakref.finalize”对我来说似乎是最有希望的。但是,文档底部有一条注释: 注意:确保 func、args 和 kwargs 不直接或间接拥有对 obj 的任何引用非常重要,否则 obj 将永远不会被垃圾回收。特别是,func 不应该是 obj 的绑定方法。 因为我想保存该对象的字段,所以我会引用它们,从而遇到这个问题。

这是否意味着对象

__exit__

函数永远不会被调用,或者直到程序崩溃/退出才会被调用?

执行此操作的 Python 方式是什么?

这有点hacky,你仍然包装你的代码,但我通常只是将 

main()

包装在

try
python save contextmanager finalizer
2个回答
2
投票
except

块中。

然后你可以用 
except
来处理
pdb.set_trace()
,这意味着无论你遇到什么异常,你的程序都会进入交互式终端而不是中断。

之后,您可以手动检查错误并将任何处理后的数据转储到pickle或任何您想做的事情中。修复错误后,设置代码来读取 pickle 并从停止的地方继续。

    
根据

CasualScience

的回答,我发现

pdb.set_trace()

0
投票
except

块)的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后,控制台将进入事后调试,可以像使用GUI调试器一样使用pdb命令进行调试。

继续上面的例子:

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

© www.soinside.com 2019 - 2024. All rights reserved.