Python 有无某种实现 Checkpoint / Snapshot 的包?

2022-05-09 15:43:54 +08:00
 CatCode

需求:一个步骤非常多,执行时间很长的脚本。在其中某些时刻,可以创建一个检查点文件,把当前状态(变量、执行上下文之类的)给保存下来。如果当前进程在某个时刻因为某些原因被 kill 了,可以从之前保存的检查点处继续(除了系统时间、进程号之类的变了,其他的都一样)。就像游戏里面的手动存档机制一样。

类似于:

a = do_something()
checkpoint.save("ck01.bin")
b = do_other_thing1(a)
do_other_thing2(a, b)

例如正在执行do_other_thing2(a, b)的时候被 kill 了,可以恢复从ck01.bin文件里面恢复

checkpoint.load("ck01.bin")
checkpoint.continue()

就会从b = do_other_thing1(a)处开始重新执行。

不知道 V 友们有没有见过比较成熟的实现类似功能的包,或者需要参考哪些方面的内容。 (很久之前我自己是糊了一个,但是用起来限制太大。所有要保存的参数必须放到一个字典里面,并且各种手动传递,非常蛋疼)

2851 次点击
所在节点    Python
22 条回复
est
2022-05-09 15:47:05 +08:00
请使用泡菜(pickle)模块
xupefei
2022-05-09 15:47:06 +08:00
dill
Latin
2022-05-09 15:49:59 +08:00
gh 关键词检索
发现以下适配你需求的东西
https://github.com/a-rahimi/python-checkpointing2
mobbdeep
2022-05-09 15:50:36 +08:00
@est pickle 应该是酸黄瓜吧
bbbbbbbbbyron
2022-05-09 15:56:19 +08:00
可以试试 joblib, 提供自动的 checkpoint 管理
CatCode
2022-05-09 15:58:34 +08:00
@est 要实现的话 pickle 肯定是要用到的。我想要的是更高基本的 api
CatCode
2022-05-09 16:39:05 +08:00
joblib 似乎不是专为这个目的开发的,看了一下官网的例子 用起来似乎不那么直观,更多的是用于缓存某些变量的计算进度。

python-checkpointing2 似乎对 CPython 的依赖度非常高,如果不采用 CPython 可能会炸
dill 似乎也非常依赖于 CPython ?看了 dill 的 test_session.py 依然云里雾里,不知道怎么用
catsoul
2022-05-09 16:41:24 +08:00
@CatCode 总得牺牲一点代价的,要不就只能自己上...
LeeReamond
2022-05-09 17:21:12 +08:00
@CatCode 感觉 cpython 似乎并无此类功能,要不然 jupyter notebook 也无需用到 ironpython 。自己实现的话多进程显然是一个简单的方案,特定点位 fork 一下就什么都有了,如果一定要落盘的话,就算追踪字节码能够实现某种程度的状态保存,遇到不可序列化的或者复杂对象也不太好办
lolizeppelin
2022-05-09 18:26:23 +08:00
taskflow 支持保存

但是只能保存基本数据结构,自定义类可以和字典互相转化就可以保存

或者说 taskflow 就是干这个的
lolizeppelin
2022-05-09 18:26:47 +08:00
lolizeppelin
2022-05-09 18:30:30 +08:00
哦你要保存本身进程信息啊...额这...
推荐错了
CatCode
2022-05-09 18:36:25 +08:00
@lolizeppelin 233333
不过这个我大概看了一下文档,也获得了一些“如果要自己做,哪些功能可以搞一搞”的启发
lolizeppelin
2022-05-09 19:27:29 +08:00
-_,- 如果可以参考直接用也是不错的
这玩意本来就是用来处理复杂冗长的虚拟机创建流程而开发的
ch2
2022-05-09 19:38:03 +08:00
你想要这么 toplevel 的 api ,不太可能
你用的端口、pid 、文件被别的进程占用或者改动了咋办?你建立的 tcp 长连接被 reset 了咋办?直接 crash?
对整个进程 checkpoint 的工具确实有,它叫 CRIU
不过如果你不配合容器一起用,这玩意基本上没有可用性的
而且它对进程 checkpoint 之后的外部环境不可变性要求非常高,提到的那几个条件必须全部满足才能保证 restore 后的进程仍然能跑
sujin190
2022-05-09 19:42:26 +08:00
pyflink 这种能满足?
CatCode
2022-05-09 22:30:34 +08:00
@ch2 我既然有这个需求,端口、文件、TCP 连接这些肯定会添加额外的代码处理,或者这些方面,我添加检查点的位置会在没有 TCP 链接、所有打开的文件已经关闭这种情况下进行。类比于游戏,游戏里可不是随时都能手动存档的。
换句话说,我要处理的任务可能是分段的:前一段和后一段不搭着,只有一些变量要传递。
ch2
2022-05-10 00:01:35 +08:00
@CatCode #17 在你能够保证严格的外部条件不变的情况下,可以手动调用 docker checkpoint create 命令将 python 进程制作为快照,再使用 docker checkpoint restore 命令进行还原:
https://docs.docker.com/engine/reference/commandline/checkpoint/
CatCode
2022-05-10 08:31:40 +08:00
@ch2 这个是依赖于 docker 的 依赖外部环境而不是 Python 本身了
如果可以考虑外部软件,不考虑“重量”的话,直接用虚拟机快照效果更好,端口文件那些都不需要考虑了(笑)
我期望的是 Python 自身实现
ch2
2022-05-10 10:21:00 +08:00
@CatCode 你可以参考 CRIU 的代码,为了保存和恢复一个进程的运行时状态他们做了多少 hack ,我相信没有人比他们更有毅力跟恒心坚持于这个目标。你想要的无非是一个 Python 版本的 CRIU 实现,或者是一个 Python 的 libcriu 引用。
但是不使用容器,非常难以避免因为环境改变导致的进程还原冲突。举个例子:为了避免 pid 被别的进程占了无法还原,你得在一开始就用 pid namespace 给你的 Python 进程开一个命名空间,但是容器在一开始创建的隔离环境就包含了各种命名空间,顺手把网络跟存储挂载都解决了。而且你的进程必须脱离 tty 运行,否则还原的时候找不到之前的 shell 也还原不成直接 core dump 。
这也就是只有容器才提供了进程级别 checkpoint 功能的原因,你自己想做进程的 checkpoint 最后无非都还要走一遍容器的老路,否则你会遇到各种 bad case ,无法 checkpoint 无法 restore 。
最简单的例子你可以 apt-get install criu ,然后试试 criu dump 你的 Python 进程,看看能不能顺利 dump

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/851762

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX