Execute user-input pdb or ipdb commands programmatically in Python
Asked Answered
B

1

6

I'm working with a PyQt application, so before debugging can begin, in the Python file, I have the lines pyqtRemoveInputHook() to stop the event loop and then ipdb.set_trace(). This enters the interactive debug session via the terminal. When done debugging, I need to manually type into the terminal c; pyqtRestoreInputHook() to continue running the program and to restore the event loop. The c tells ipdb or pdb to continue and the pyqtRestoreInputHook() is interpreted as Python code. While it's not too big of a hassle, I'd like to somehow create a function that allows python commands to tell ipdb or pdb that a given string was a pseudo keyboard command.

In other words, I'm trying to find a function that's basically ipdb.run_user_input(my_string) where my_string can be any of the normal ipdb or pdb functions like next, c, step, list, etc.

Thanks!

Ballast answered 26/10, 2018 at 19:13 Comment(0)
T
3

I was looking for something similar, but it doesn't seem like pdb lets run you a sequence of pdb commands programmatically.

However, it does let you read a sequence of pdb commands from a .pdbrc file, which get executed immediately on dropping into any pdb session.

Thankfully, according to the documentation:

The run* functions and set_trace() are aliases for instantiating the Pdb class and calling the method of the same name.

... in other words, each call to pdb seems to instantiate a new instance of the class, with the readrc parameter defaulting to true, and therefore you can create a new .pdbrc file just before the call, and the new file will be picked up and executed.

Therefore, it should be sufficient to write a .pdbrc file in the current directory just before calling pdb.set_trace, containing the sequence of commands you're interested in. E.g.

import pdb;

with open( '.pdbrc', 'w') as f: 
    print( "print('Hello from pdbrc')", file = f )
    print( "continue", file = f )

pdb.set_trace()

with open( '.pdbrc', 'w') as f:
    print( "print('Hello again!')", file = f )

pdb.set_trace()

In the above example, the first pdb.set_trace() should print "Hello from pdbrc" and immediately continue with program execution, and then the second pdb.set_trace() should print "Hello again!" and remain in the pdb environment.


Warning: If you have an existing .pdbrc file in your home directory that you rely on, make sure you're not going to overwrite this (e.g. make sure you have a backup).


UPDATE it turns out that you can append to the rc lines programmatically, which eliminates the need to create a file on disk completely. Note that you can't do this on the module pdb directly, you need to create a Pdb class instance first.

import pdb
pdb = pdb.Pdb()   # or pdb = pdb.Pdb( readrc = False )  if you want to ignore your existing .pdbrc
pdb.rcLines.append( "print('Hellooo')" )
pdb.rcLines.append( "continue" )
pdb.set_trace()

An advantage of this is that, unless you call using the readrc = False argument, your existing .pdbrc file will be honoured, and any commands you append programmatically will effectively be appended to the pdbrc-derived commands.

However, note that for some reason, after a successful first trace via this pdb instance, the pdb.rcLines list gets cleared and you should repopulate it with any new commands you need in order to perform a second trace from this instance.

Told answered 15/12, 2020 at 21:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.