How to debug python CLI that takes stdin?

前端 未结 4 760
悲&欢浪女
悲&欢浪女 2020-12-28 14:08

I\'m trying to debug a Python CLI I wrote that can take its arguments from stdin. A simple test case would have the output of

echo \"test\" | python mytool.p         


        
相关标签:
4条回答
  • 2020-12-28 14:43

    Another option is to create you own Pdb object, and set there the stdin and stdout. My proof of concept involves 2 terminals, but for sure some work can be merged some kind of very unsecure network server.

    1. Create two fifos: mkfifo fifo_stdin mkfifo fifo_stdout

    2. In one terminal, open stdout on background, and write to stdin: cat fifo_stdout & cat > fifo_stdin

    3. In your python code/console create the pdb object, and use it: import pdb mypdb=pdb.Pdb(stdin=open('fifo_stdin','r'), stdout=open('fifo_stdout','w')) ... mypdb.set_trace() ...
    4. Profit!

    You should be able to use pdb on the first console.

    The only drawback is having to use your custom pdb, but some monkey patching at init (PYTHONSTARTUP or similar) can help:

    import pdb mypdb=pdb.Pdb(stdin=open('fifo_stdin','r'), stdout=open('fifo_stdout','w')) pdb.set_trace=mydbp.set_trace

    0 讨论(0)
  • 2020-12-28 15:02

    When you use pdb(or any other python debugger) it acquires stdin for debug commands, that's why you get NameError: name 'test' is not defined.

    For example this command will quit debugger at the begging of a runtime and you wont get this error(nor interactive debugging) for one run:

    (echo cont;echo "test") | python -m pdb mytool.py

    0 讨论(0)
  • 2020-12-28 15:04

    You can use another file descriptor. With bash you can create a new file descriptor with:

    exec 3<> test.txt
    

    And then on your python file have something like:

    #!/usr/bin/python
    
    # Use fd 3 as another stdin file.
    import os
    stdin=os.fdopen(3)
    
    while True:
        s=stdin.readline()
        import pdb; pdb.set_trace()
        print len(s)
    

    Just runing your script will use that test.txt as input, and you can use stdin on stdin. It can be used as well with pipes if you need.

    0 讨论(0)
  • 2020-12-28 15:04

    Your controlling TTY is still a terminal, right? Use this instead of pdb.set_trace.

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

    Haven't gotten readline to autocomplete under these circumstances. Up arrow won't work either, or any other of the readline niceties.

    0 讨论(0)
提交回复
热议问题