24

Is there a way to save pdb (python debugger) command history across sessions? Also, can I specify history length?

This is similar to the question How can I make gdb save the command history?, however for pdb instead of gdb.

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
vkontori
  • 1,187
  • 1
  • 10
  • 17

6 Answers6

19

See this post. It is possible to save history in pdb. By default, pdb does not read multiple lines. So all functions need to be on a single line.

In ~/.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)
Community
  • 1
  • 1
irritable_phd_syndrome
  • 4,631
  • 3
  • 32
  • 60
  • Make sure you also remove old entries from this file, it can grow really big ~2GB in my case in just a month. – ilija139 Feb 08 '19 at 04:54
  • [readline.set_history_length](https://docs.python.org/3/library/readline.html#readline.set_history_length) can be used to truncate history size automatically. – niekas Nov 07 '22 at 20:28
15

Credits: https://wiki.python.org/moin/PdbRcIdea

pdb uses readline so we can instruct readline to save history:

.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

For the drop-in replacement pdb++, copy the above function code into the setup() method:

from pdb import DefaultConfig, Pdb


class Config(DefaultConfig):
    def setup(self, pdb):
        ## Save history across sessions
        #
        import readline
        ...
ankostis
  • 8,579
  • 3
  • 47
  • 61
olejorgenb
  • 1,203
  • 14
  • 25
  • This works beautifully for the `pdbpp / pdb++` debugger. Thanks! – Christian Long Jan 27 '21 at 17:08
  • To put the history file in your home dir, see [this answer](https://stackoverflow.com/a/65924715/456550). – Christian Long Jan 27 '21 at 17:58
  • This was helpful, but I noticed that the .pdbrc file is read _every time the debugger breaks in_. That means every time you run `continue` it'll reload the file. the atexit handler only runs when the whole program exits. So this stomps on updates to your session's history. I ended up using a hack with NameError to only execute the initialization once. – Nick Gerner Oct 12 '22 at 22:32
  • Still working, Ubuntu 23.04, Python 3.10.7. Thank you! – Sergio Belevskij Apr 29 '23 at 20:00
4

An example for clearing / reading / printing the current pdb history:

(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])

output:

[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])']

reference:

two liner without readline.clear_history for what has been input to pdb so far:

from pprint import pprint; import readline
pprint([readline.get_history_item(x) for x in range(readline.get_current_history_length() + 1)])
jmunsch
  • 22,771
  • 11
  • 93
  • 114
2

Extending @olejorgenb's excellent answer, I wanted the history file in my home directory rather than in the current directory, so I used 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)

This is my setup for configuring pdbpp (an improved debugger, aka pdb++, https://pypi.org/project/pdbpp/). You can use the same idea along with @olejorgenb's answer to configure regular pdb.

Christian Long
  • 10,385
  • 6
  • 60
  • 58
1

I don't believe there is a way with "stock" pdb. But I wrote a replacement debugger that does that.

just install Pycopia from source: http://code.google.com/p/pycopia/source/checkout and it's in pycopia.debugger.

Keith
  • 42,110
  • 11
  • 57
  • 76
-2

I think you can do this with IPython:

http://ipython.org/ipython-doc/stable/interactive/tutorial.html#history

ipdb replacement for pdb:

http://pypi.python.org/pypi/ipdb

Mikko Ohtamaa
  • 82,057
  • 50
  • 264
  • 435
  • 1
    Are you sure this can be done with ipdb? I was not able to get my history from my old ipdb sessions. – Phani Nov 08 '14 at 00:23
  • IPDB doesn't support the same magic commands as IPython does. Unless you can show me a way to input `%magic-commands` in IPDB, the downvote stays. – Błażej Michalik Mar 06 '18 at 09:35