在Python中,有什么方法可以保存/转储/序列化PDB调试会话吗



我一直在使用Python程序,这些程序需要几个小时才能完成,但偶尔会崩溃。为了调试,到目前为止,我一直在添加条件断点,每当出现问题时,这些断点都会让我进入PDB会话。这很好,因为很难确定问题的确切原因,而且交互式会话可以让我探索整个程序(包括所有堆栈帧等等(。

唯一的问题是,如果我不小心关闭或破坏了调试会话,我需要重新启动整个程序!到达断点需要几个小时!我真的非常真的喜欢序列化PDB会话并多次重新打开它的方式。像这样的东西存在吗?我已经研究了dill来序列化解释器会话,不幸的是,我的一些类型无法序列化(它也不适合后续的代码更改(。谢谢

您还没有指定您选择的操作系统,但在linux世界中有一个criu实用程序-https://criu.org/Main_Page,可用于保存应用程序状态。现在有很多陷阱,尤其是基于tty的应用程序(请参阅https://criu.org/Advanced_usage#Shell_jobs_C.2FR)但这里有一个例子。

  1. 我得到了一个带有pdb调试点的简单python应用程序,让我们称之为app.py:

    print("hello")
    import pdb; pdb.set_trace()
    print("world")
    
  2. 使用python app.py运行此应用程序后,您将获得预期的

    hello
    > /home/user/app.py(3)<module>()
    -> print("world")
    
  3. pgrep -f app.py获取你的pid,在我的情况下是17060

  4. 创建一个文件夹来转储您的流程

    mkdir /tmp/criu
    
  5. 使用转储您的流程

    sudo criu dump -D /tmp/criu -t 17060 --shell-job 
    

    请注意,您当前的进程将被终止(AFAIK由于--shell作业密钥,请参阅上面的链接(。你会看到

    (Pdb) [1]    17060 killed     python app.py
    

    在你的tty 中

  6. 使用恢复您的流程

    sudo criu restore -D /tmp/criu --shell-job
    

    您的tty将在使用此命令的同一窗口中恢复。

  7. 由于附加了调试器,您可以键入c并输入以查看它是否真的工作。这是我的机器上的结果:

    (Pdb) c
    world
    

希望这有帮助,有很多陷阱可能会使这种方法对你来说不可行。

另一种方法是每次在VM、快照磁盘和内存中运行代码。从资源角度来看,这可能不是最好的解决方案,但许多管理程序都有一个很好的UI,甚至可以使用shell实用程序来控制虚拟机的状态。快照技术现在在任何系统管理程序中都很成熟,你不应该遇到任何问题。设置远程调试,并在恢复快照后连接到您喜爱的IDE。

编辑:如果你在容器中运行应用程序,并且你的操作系统支持podman和criu 3.11+,也有一种简单的方法可以做到这一点

https://criu.org/Podman

你可以使用类似的东西

podman run -d --name your_container_name your_image

使用进行快照

podman container checkpoint your_container_id

要恢复,请使用

podman container restore your_container_id

所有这些命令都需要root权限。不幸的是,我没能测试它,因为我的发行版提供了criu3.8,而podman3.11是必需的。

Docker中提供了与实验标志相同的功能,请参阅https://criu.org/Docker

最新更新