在 Python 中,有什么方法可以 save/dump/serialize PDB 调试会话吗?
In Python, is there any way to save/dump/serialize a PDB debugging session?
我一直在使用 Python 需要几个小时才能完成的程序,但偶尔会崩溃。为了进行调试,到目前为止,我一直在添加条件断点,只要出现问题,这些断点就会让我进入 PDB 会话。这很棒,因为很难查明问题的确切原因,而交互式会话让我可以探索整个程序(包括所有堆栈帧等)。
唯一的问题是,如果我不小心关闭或崩溃了我的调试会话,我需要重新启动整个程序!到达我的断点需要几个小时!我会 really,really 喜欢序列化 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) 但这里有一个例子。
我得到了一个带有 pdb 调试点的简单 python 应用程序,我们称它为 app.py
:
print("hello")
import pdb; pdb.set_trace()
print("world")
在 运行 将此应用程序与 python app.py
结合后,您将获得预期
hello
> /home/user/app.py(3)<module>()
-> print("world")
用 pgrep -f app.py
获取你的 pid,在我的例子中是 17060
创建一个文件夹来转储您的进程
mkdir /tmp/criu
使用
转储你的进程
sudo criu dump -D /tmp/criu -t 17060 --shell-job
请注意,您当前的进程将被终止(AFAIK 由于 --shell-job 键,请参阅上面的 link)。
你会看到
(Pdb) [1] 17060 killed python app.py
在你的 tty 中
使用
恢复您的进程
sudo criu restore -D /tmp/criu --shell-job
您的 tty 将在您使用此命令的同一 window 中恢复。
由于附加了调试器,您可以键入 c
并输入以查看它是否真的有效。这是我机器上的结果:
(Pdb) c
world
希望对您有所帮助,有很多陷阱可能会使这种方法对您不可行。
另一种方法是 运行 您的代码每次都在 VM 和快照磁盘和内存中。它可能不是资源方面的最佳解决方案,但许多虚拟机管理程序都有很好的 UI 甚至 shell 实用程序来控制虚拟机的状态。如今,快照技术在任何管理程序中都已成熟,您不应该 运行 遇到任何问题。恢复快照后,设置远程调试并连接您最喜欢的 IDE。
编辑:如果您运行在容器中安装您的应用程序并且您OS支持 podman 和 criu 3.11+
,还有一种简单的方法可以做到这一点
你可以使用像
这样的东西
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
我一直在使用 Python 需要几个小时才能完成的程序,但偶尔会崩溃。为了进行调试,到目前为止,我一直在添加条件断点,只要出现问题,这些断点就会让我进入 PDB 会话。这很棒,因为很难查明问题的确切原因,而交互式会话让我可以探索整个程序(包括所有堆栈帧等)。
唯一的问题是,如果我不小心关闭或崩溃了我的调试会话,我需要重新启动整个程序!到达我的断点需要几个小时!我会 really,really 喜欢序列化 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) 但这里有一个例子。
我得到了一个带有 pdb 调试点的简单 python 应用程序,我们称它为
app.py
:print("hello") import pdb; pdb.set_trace() print("world")
在 运行 将此应用程序与
python app.py
结合后,您将获得预期hello > /home/user/app.py(3)<module>() -> print("world")
用
pgrep -f app.py
获取你的 pid,在我的例子中是 17060创建一个文件夹来转储您的进程
mkdir /tmp/criu
使用
转储你的进程sudo criu dump -D /tmp/criu -t 17060 --shell-job
请注意,您当前的进程将被终止(AFAIK 由于 --shell-job 键,请参阅上面的 link)。 你会看到
(Pdb) [1] 17060 killed python app.py
在你的 tty 中
使用
恢复您的进程sudo criu restore -D /tmp/criu --shell-job
您的 tty 将在您使用此命令的同一 window 中恢复。
由于附加了调试器,您可以键入
c
并输入以查看它是否真的有效。这是我机器上的结果:(Pdb) c world
希望对您有所帮助,有很多陷阱可能会使这种方法对您不可行。
另一种方法是 运行 您的代码每次都在 VM 和快照磁盘和内存中。它可能不是资源方面的最佳解决方案,但许多虚拟机管理程序都有很好的 UI 甚至 shell 实用程序来控制虚拟机的状态。如今,快照技术在任何管理程序中都已成熟,您不应该 运行 遇到任何问题。恢复快照后,设置远程调试并连接您最喜欢的 IDE。
编辑:如果您运行在容器中安装您的应用程序并且您OS支持 podman 和 criu 3.11+
,还有一种简单的方法可以做到这一点你可以使用像
这样的东西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