Here is a sample python script.
import sys
print("Hello, world!")
for i, line in enumerate(sys.stdin):
print(line)
print(f"Before breakpoint: {i}")
breakpoint()
print(f"After breakpoint: {i}")
Running seq 1 10 | python tmp.py
launches debugger at the specified breakpoint, however, it automatically reads all the stdin.
seq 1 10 | python tmp.py
Hello, world!
1
Before breakpoint: 0
> .../tmp.py(9)<module>()
-> print(f"After breakpoint: {i}")
(Pdb) 2
(Pdb) 3
(Pdb) 4
(Pdb) 5
(Pdb) 6
(Pdb) 7
(Pdb) 8
(Pdb) 9
(Pdb) 10
(Pdb)
Traceback (most recent call last):
File ".../tmp.py", line 9, in <module>
print(f"After breakpoint: {i}")
File ".../tmp.py", line 9, in <module>
print(f"After breakpoint: {i}")
File ".../python3.10/bdb.py", line 90, in trace_dispatch
return self.dispatch_line(frame)
File ".../python3.10/bdb.py", line 115, in dispatch_line
if self.quitting: raise BdbQuit
bdb.BdbQuit
How to stop breakpoint()
from reading STDIN? i.e., I still want breakpoint()
but just don't want it to automatically consume and execute STDIN.
I looked into the docs[1] and it doesn't mention about this STDIN behavior, nor an option to disable it.
[1] https://docs.python.org/3.10/library/functions.html?highlight=breakpoint#breakpoint. I am using Python 3.10.9 on Ubuntu 20.04.6 LTS (WSL)
Answering my own question. Thanks to the comments, and credits to this answer [1], here is a solution that works.
The trick is to attach TTY as STDIN/OUT/ERR for the PDB while leaving STDIN/OUT/ERR intact.
import sys
print("Hello, world!")
def tty_pdb():
from contextlib import (_RedirectStream,
redirect_stdout, redirect_stderr)
class redirect_stdin(_RedirectStream):
_stream = 'stdin'
with open('/dev/tty', 'r') as new_stdin, \
open('/dev/tty', 'w') as new_stdout, \
open('/dev/tty', 'w') as new_stderr, \
redirect_stdin(new_stdin), \
redirect_stdout(new_stdout), redirect_stderr(new_stderr):
__import__('pdb').set_trace()
for i, line in enumerate(sys.stdin):
print(line)
print(f"Before breakpoint: {i}")
tty_pdb()
print(f"After breakpoint: {i}")
It's elegant -- no need to tweak the scripts that invoke python program! Credits to the author of [1] (I've already upvoted their answer).