在 Python 中,有没有办法保存/转储/序列化 PDB 调试会话?

yaw*_*awn 5 python debugging serialization dump pdb

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

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

And*_*rew 4

您还没有指定您选择的操作系统,但是在 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")
    
    Run Code Online (Sandbox Code Playgroud)
  2. 运行此应用程序后,python app.py您会得到预期的结果

    hello
    > /home/user/app.py(3)<module>()
    -> print("world")
    
    Run Code Online (Sandbox Code Playgroud)
  3. 获取你的 pid pgrep -f app.py,在我的例子中是 17060

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

    mkdir /tmp/criu
    
    Run Code Online (Sandbox Code Playgroud)
  5. 转储你的进程

    sudo criu dump -D /tmp/criu -t 17060 --shell-job 
    
    Run Code Online (Sandbox Code Playgroud)

    请注意,您当前的进程将被终止(据我所知,由于 --shell-job 键,请参阅上面的链接)。你会看到的

    (Pdb) [1]    17060 killed     python app.py
    
    Run Code Online (Sandbox Code Playgroud)

    在你的终端里

  6. 恢复您的进程

    sudo criu restore -D /tmp/criu --shell-job
    
    Run Code Online (Sandbox Code Playgroud)

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

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

    (Pdb) c
    world
    
    Run Code Online (Sandbox Code Playgroud)

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

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

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

https://criu.org/Podman

你可以使用类似的东西

podman run -d --name your_container_name your_image
Run Code Online (Sandbox Code Playgroud)

快照使用

podman container checkpoint your_container_id
Run Code Online (Sandbox Code Playgroud)

恢复使用

podman container restore your_container_id
Run Code Online (Sandbox Code Playgroud)

所有这些命令都需要 root 权限。不幸的是我无法测试它,因为我的发行版提供 criu 3.8,而 podman 需要 3.11。

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