V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
CatCode
V2EX  ›  Python

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

  •  
  •   CatCode · 2022-05-09 15:43:54 +08:00 · 3087 次点击
    这是一个创建于 936 天前的主题,其中的信息可能已经有所发展或是发生改变。

    需求:一个步骤非常多,执行时间很长的脚本。在其中某些时刻,可以创建一个检查点文件,把当前状态(变量、执行上下文之类的)给保存下来。如果当前进程在某个时刻因为某些原因被 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 友们有没有见过比较成熟的实现类似功能的包,或者需要参考哪些方面的内容。 (很久之前我自己是糊了一个,但是用起来限制太大。所有要保存的参数必须放到一个字典里面,并且各种手动传递,非常蛋疼)

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

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

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

    或者说 taskflow 就是干这个的
    lolizeppelin
        11
    lolizeppelin  
       2022-05-09 18:26:47 +08:00
    lolizeppelin
        12
    lolizeppelin  
       2022-05-09 18:30:30 +08:00
    哦你要保存本身进程信息啊...额这...
    推荐错了
    CatCode
        13
    CatCode  
    OP
       2022-05-09 18:36:25 +08:00
    @lolizeppelin 233333
    不过这个我大概看了一下文档,也获得了一些“如果要自己做,哪些功能可以搞一搞”的启发
    lolizeppelin
        14
    lolizeppelin  
       2022-05-09 19:27:29 +08:00
    -_,- 如果可以参考直接用也是不错的
    这玩意本来就是用来处理复杂冗长的虚拟机创建流程而开发的
    ch2
        15
    ch2  
       2022-05-09 19:38:03 +08:00
    你想要这么 toplevel 的 api ,不太可能
    你用的端口、pid 、文件被别的进程占用或者改动了咋办?你建立的 tcp 长连接被 reset 了咋办?直接 crash?
    对整个进程 checkpoint 的工具确实有,它叫 CRIU
    不过如果你不配合容器一起用,这玩意基本上没有可用性的
    而且它对进程 checkpoint 之后的外部环境不可变性要求非常高,提到的那几个条件必须全部满足才能保证 restore 后的进程仍然能跑
    sujin190
        16
    sujin190  
       2022-05-09 19:42:26 +08:00
    pyflink 这种能满足?
    CatCode
        17
    CatCode  
    OP
       2022-05-09 22:30:34 +08:00
    @ch2 我既然有这个需求,端口、文件、TCP 连接这些肯定会添加额外的代码处理,或者这些方面,我添加检查点的位置会在没有 TCP 链接、所有打开的文件已经关闭这种情况下进行。类比于游戏,游戏里可不是随时都能手动存档的。
    换句话说,我要处理的任务可能是分段的:前一段和后一段不搭着,只有一些变量要传递。
    ch2
        18
    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
        19
    CatCode  
    OP
       2022-05-10 08:31:40 +08:00
    @ch2 这个是依赖于 docker 的 依赖外部环境而不是 Python 本身了
    如果可以考虑外部软件,不考虑“重量”的话,直接用虚拟机快照效果更好,端口文件那些都不需要考虑了(笑)
    我期望的是 Python 自身实现
    ch2
        20
    ch2  
       2022-05-10 10:21:00 +08:00 via iPhone
    @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
    CatCode
        21
    CatCode  
    OP
       2022-05-10 10:47:41 +08:00
    @ch2 我说过我并非想处理每一种情况。我已经注明了不考虑多线程 /多进程——意味着我创建检查点的时候只有一个线程和进程。17 楼里我也说了检查点的创建是在没有 TCP 链接、所有打开的文件已经关闭的情况。我的任务也不依赖于 PID 号,所以变了也无所谓。17 楼真的说的很明白了,是一段一段地处理大量操作。如果还不明白,找个类比,GitHub Actions 里面的 steps 。
    gengchun
        22
    gengchun  
       2022-05-10 11:25:34 +08:00
    前段时间有个类似的需求,我是每步直接缓存结果,类似于 http GET 缓存的处理方式,通过一个标志符和一个上下文 hashmap 做键值。每步就检查有没有缓存,有就直接返回缓存结果,没有就算一次。

    检查缓存的逻辑本身,当然可以用装饰器语法加上。不需要考虑多子任务,并发结果合并什么的,感觉用不到什么高级的库。

    只是想开拓一下思路。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1020 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 19:55 · PVG 03:55 · LAX 11:55 · JFK 14:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.