在 pdb 中保存命令历史记录

25

有没有办法在不同的会话中保存pdb(Python调试器)命令历史记录?同时,我可以指定历史记录长度吗?

这类似于问题如何使gdb保存命令历史记录?,但是针对的是pdb而不是gdb。


Ubuntu 11.04 Python 2.7.1+ (r271:86832, Apr 11 2011, 18:13:53) [GCC 4.5.2] 在 Linux2 上。 - vkontori
你解决了这个问题吗?我也想要一个类似的功能。 - Phani
6个回答

19

请参阅帖子。在pdb中,可以保存历史记录。默认情况下,pdb不读取多行,因此所有函数都需要在单一行上。

在~/.pdbrc文件中:

import atexit
import os
import readline

historyPath = os.path.expanduser("~/.pyhistory")

def save_history(historyPath=historyPath): import readline; readline.write_history_file(historyPath)

if os.path.exists(historyPath): readline.read_history_file(historyPath)

atexit.register(save_history, historyPath=historyPath)

请确保从该文件中删除旧条目,否则它可能会在一个月内变得非常大,比如我的情况下可能达到2GB。 - ilija139
readline.set_history_length 可以用于自动截断历史记录大小。 - niekas

16

致谢: https://wiki.python.org/moin/PdbRcIdea

pdb使用readline,因此我们可以指示readline保存历史记录:

.pdbrc

# NB: `pdb` only accepts single-line statements
import os
with open(os.path.expanduser("~/.pdbrc.py")) as _f: _f = _f.read()
exec(_f)
del _f

.pdbrc.py

def _pdbrc_init():
    # Save history across sessions
    import readline
    histfile = ".pdb-pyhist"
    try:
        readline.read_history_file(histfile)
    except IOError:
        pass
    import atexit
    atexit.register(readline.write_history_file, histfile)
    readline.set_history_length(500)

_pdbrc_init()
del _pdbrc_init

对于可直接替换 pdb++ 的解决方法,将上述函数代码复制到 setup() 方法中:

from pdb import DefaultConfig, Pdb


class Config(DefaultConfig):
    def setup(self, pdb):
        ## Save history across sessions
        #
        import readline
        ...

这对于 pdbpp / pdb++ 调试器非常有效。谢谢! - Christian Long
将历史文件放在您的主目录中,请参阅此答案 - Christian Long
这很有帮助,但我注意到.pdbrc文件在每次调试器中断时都会被读取。这意味着每次运行continue时它都会重新加载该文件。atexit处理程序仅在整个程序退出时运行。因此,这会覆盖对会话历史记录的更新。最终,我使用了一个NameError的hack来仅执行一次初始化。 - Nick Gerner
仍在工作,Ubuntu 23.04,Python 3.10.7。谢谢! - Sergio Belevskij

4
清除/读取/打印当前pdb历史记录的示例:
(Pdb) readline.clear_history()
(Pdb) print('hello pdb')
hello pdb
(Pdb) from pprint import pprint; import readline
(Pdb) y = range(readline.get_current_history_length() + 2)
(Pdb) print([readline.get_history_item(x) for x in y])

输出:

[None, 
"print('hello pdb')", 
'from pprint import pprint; import readline', 
'y = range(readline.get_current_history_length() + 2)',
'print([readline.get_history_item(x) for x in y])']

参考资料:

两行代码(不含 readline.clear_history)以查看已输入到 pdb 中的内容:

from pprint import pprint; import readline
pprint([readline.get_history_item(x) for x in range(readline.get_current_history_length() + 1)])

1
这是一个有用的示例,展示了如何访问和删除由readline库记录的历史记录。 - Guido van Steen

2

在扩展@olejorgenb的出色答案的基础上,我希望将历史文件保存在我的主目录中,而不是当前目录中,因此我使用了pathlib.Path.expanduser

import pdb

class Config(pdb.DefaultConfig):

    def setup(self, pdb):
        # Save history across sessions
        import readline
        from pathlib import Path
        histfile_path = Path("~/.pdb-pyhist").expanduser()

        try:
            readline.read_history_file(histfile_path)
        except IOError:
            pass

        import atexit
        atexit.register(readline.write_history_file, histfile_path)
        readline.set_history_length(500)


这是我为配置 pdbpp(一个改进的调试器,也称为 pdb++https://pypi.org/project/pdbpp/)而进行的设置。您可以使用相同的想法以及 @olejorgenb 的 答案 来配置常规的 pdb

你不应该在 setup 函数的第一行使用 super().setup(pdb) 吗? - tigerjack

1

我不相信使用“标准”的pdb有这种方法。但是我编写了一个替代调试器来实现这个功能。

只需从源代码安装Pycopia:http://code.google.com/p/pycopia/source/checkout,然后在pycopia.debugger中即可找到它。


-2

1
你确定可以用ipdb做到这一点吗?我无法从以前的ipdb会话中获取历史记录。 - Phani
IPDB不支持与IPython相同的魔术命令。除非你能向我展示在IPDB中输入“%magic-commands”的方法,否则我会保持反对态度。 - Błażej Michalik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接