我想要
但是,由于第 2 步可能需要几个小时,我想确保在出现意外异常时保存进度。 数据被加载到对象中以便于使用它。 我想到的第一件事是将对象类转换为上下文管理器并使用
with
语句。然而,我实际上必须在该 with
语句中编写我的整个程序,这感觉不对。
所以我环顾四周,发现“这个问题”本质上要求同样的事情。在答案中,“这个”建议“weakref.finalize”对我来说似乎是最有希望的。但是,文档底部有一条注释:
注意:确保 func、args 和 kwargs 不直接或间接拥有对 obj 的任何引用非常重要,否则 obj 将永远不会被垃圾回收。特别是,func 不应该是 obj 的绑定方法。
因为我想保存该对象的字段,所以我会引用它们,从而遇到这个问题。
这是否意味着对象函数永远不会被调用,或者直到程序崩溃/退出才会被调用?
__exit__
执行此操作的 Python 方式是什么?
这有点hacky,你仍然包装你的代码,但我通常只是将
main()
包装在
try
except
块中。
然后你可以用except
来处理 pdb.set_trace()
,这意味着无论你遇到什么异常,你的程序都会进入交互式终端而不是中断。
之后,您可以手动检查错误并将任何处理后的数据转储到pickle或任何您想做的事情中。修复错误后,设置代码来读取 pickle 并从停止的地方继续。
根据CasualScience
的回答,我发现
pdb.set_trace()
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