Reputation: 2939
I have a python script that reads stdin via a pipe, and I cannot seem to use it with pdb.set_trace().
my_script.py:
#!/usr/bin/env python
import sys
import pdb
def main():
for line in sys.stdin:
print "Printing a line: " +line
if __name__=='__main__':
status = main()
Suppose tempfile.csv is some file with two lines,
$ cat tempfile.csv
line1
line2
then I can run my script with: $ cat tempfile.csv | ./my_script.py, and everything is fine:
$ cat tempfile.csv | ./my_script.py
Printing a line: line1
Printing a line: line2
On the other hand, if I put pdb.set_trace() anywhere then I get an error. For example, putting pdb.set_trace() below def main(), then I get
$ cat tempfile.csv | ./my_script.py
> /home/ilangmore/mobiuss/TM/branches/hadooprotype/my_script.py(7)main()
-> for line in sys.stdin:
(Pdb) *** NameError: name 'line1' is not defined
(Pdb) *** NameError: name 'line2' is not defined
(Pdb)
Traceback (most recent call last):
File "./my_script.py", line 11, in <module>
status = main()
File "./my_script.py", line 7, in main
for line in sys.stdin:
File "./my_script.py", line 7, in main
for line in sys.stdin:
File "/usr/lib/python2.7/bdb.py", line 48, in trace_dispatch
return self.dispatch_line(frame)
File "/usr/lib/python2.7/bdb.py", line 67, in dispatch_line
if self.quitting: raise BdbQuit
bdb.BdbQuit
Note that my question is probably related to this question (i.e. pdb by default reads from stdin), but I need more help.
Upvotes: 47
Views: 11294
Reputation: 728
Here's an example of what worked for me:
import sys
import pdb
lines = sys.stdin.readlines()
sys.stdin = open("/dev/tty")
pdb.set_trace()
Edit: since 3.7 you no longer need to import pdb
for set_trace
, it is available as breakpoint
, so the above only requires a sys
import.
import sys
lines = sys.stdin.readlines()
sys.stdin = open("/dev/tty")
breakpoint()
You may wish to replace sys.stdin.readlines()
above with the iterable fileinput.input()
(which defaults to sys.stdin
if the list of files in sys.argv[1:]
is empty) like so:
import fileinput
import sys
lines = fileinput.input()
sys.stdin = open("/dev/tty")
breakpoint()
Upvotes: 28
Reputation: 3664
For completeness, I made a snippet with the following code, based on the accepted answer.
import sys; sys.stdin = open('/dev/tty'); import pdb; pdb.set_trace();
Upvotes: 3
Reputation: 2452
Using the ripdb module (pip install ripdb
) solved this issue for me.
Upvotes: 5
Reputation: 480
I ran into this exact problem today. I found that Winpdb works perfectly.
Upvotes: 1
Reputation: 1458
You may want to look at how the Celery RDB (Remote Debugger) contrib module works:
https://github.com/celery/celery/blob/master/celery/contrib/rdb.py
It seems to involve a lot of stream processing, but I have tested it, and it works by allowing you to telnet into a new local network port. It's not the much better ipdb, but simply pdb.
Upvotes: 2
Reputation: 13251
The thing is: cat
will not stop sending data because your script is currently debugging. And when you going to trace, then stdin is still filled by cat
+ your keyboard. You need to choose one of them.
You can read the whole stdin, and then, set_trace() will be not filled by stdin:
sys.stdin.read()
pdb.set_trace()
Upvotes: 5