Question

If I have a program where stdout is redirected, my pdb prompts all go to the redirection, because the library was written to write to stdout.

Oftentimes this problem is subtle, causing me to think a program is hanging when it's really waiting for input.

How do people work around this? (Unfortunately, using other debuggers like winpdb is not an option).

Was it helpful?

Solution

The problem here is that PDB uses Cmd class where by default:

use_rawinput = 1

It means that Cmd will use raw_input() method by default instead of sys.stdout.readline() to read from the console . This is done because raw_input() supports history (only if readline module is loaded) and other useful bits . The only issue is that raw_input() does not support redirection, so if you have a script:

#!/usr/bin/python
name=raw_input("Enter your name: ")

and run it

> python test.py
Enter your name: Alex

but, if you run it with output redirection it will stuck

> python test.py | tee log

this is exactly what PDB uses and why it's stuck as well. As I mentioned sys.stdin.readline() supports redirection and if you rewrite the above script using readline() it should work.

Back to the original issue all you need to do is to tell Cmd to not use raw_input():

Cmd.use_rawinput = 0

or

pdb = pdb.Pdb()
pdb.use_rawinput=0
pdb.set_trace()

OTHER TIPS

This answer is just to supplement Ned's, as a way of wrapping the pdb.py main() function in a manner which doesn't require copying 40 lines just to change one of them:

# sane_pdb.py: launch Pdb with stdout on original
import sys, pdb
def fixed_pdb(Pdb=pdb.Pdb):
    '''make Pdb() tied to original stdout'''
    return Pdb(stdout=sys.__stdout__)

if __name__ == '__main__':
    pdb.Pdb = fixed_pdb
    pdb.main()

I don't know if it actually works for the questioner's problem, but it does what Ned described...

If you are invoking pdb in code, you can pass your own stdout into the constructor. sys.__stdout__ might be a good choice.

If you are invoking pdb from the command line, you could copy the main() function from pdb.py into your own sane_pdb.py. Then change the Pdb() initialization to:

pdb = Pdb(stdout=sys.__stdout__)

Then you can invoke sane_pdb.py instead of pdb.py. It's not awesome that you'd have to copy 40 lines into your own file just to change one of them, but it's an option.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top