在 Python 中,有什么方法可以 save/dump/serialize PDB 调试会话吗?

In Python, is there any way to save/dump/serialize a PDB debugging session?

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

唯一的问题是,如果我不小心关闭或崩溃了我的调试会话,我需要重新启动整个程序!到达我的断点需要几个小时!我会 reallyreally 喜欢序列化 PDB 会话并多次重新打开它的方法。有这样的东西存在吗?我已经研究过 dill 以序列化解释器会话,不幸的是我的几种类型无法序列化(它也不能很好地进行代码更改)。谢谢!

您尚未指定您选择的操作系统,但在 linux 世界中有一个 criu 实用程序 - https://criu.org/Main_Page , which can be used to save an application state. Now there are a lot of pitfalls, especially with tty-based applications (see 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-job 键,请参阅上面的 link)。 你会看到

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

    在你的 tty 中

  6. 使用

    恢复您的进程
    sudo criu restore -D /tmp/criu --shell-job
    

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

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

    (Pdb) c
    world
    

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

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

编辑:如果您运行在容器中安装您的应用程序并且您OS支持 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 权限。不幸的是我无法测试它,因为我的发行版提供了 criu 3.8,而对于 podman 3.11 是必需的。

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