如何调试使用stdin的pythoncli?

如何调试使用stdin的pythoncli?,python,stdin,pdb,command-line-interface,command-line-tool,Python,Stdin,Pdb,Command Line Interface,Command Line Tool,我正在尝试调试我编写的Python CLI,它可以从stdin获取参数。一个简单的测试用例的输出是 echo "test" | python mytool.py 相当于 python mytool.py test 我想用这个工具调试一些问题,所以我试着运行这个: echo "test" | pdb mytool.py 但我得到这个输出,然后pdb退出: > /path/to/mytool.py(5)<module>() -> ''' (Pdb) *** NameEr

我正在尝试调试我编写的Python CLI,它可以从stdin获取参数。一个简单的测试用例的输出是

echo "test" | python mytool.py
相当于

python mytool.py test
我想用这个工具调试一些问题,所以我试着运行这个:

echo "test" | pdb mytool.py
但我得到这个输出,然后pdb退出:

> /path/to/mytool.py(5)<module>()
-> '''
(Pdb) *** NameError: name 'test' is not defined
(Pdb)
/path/to/mytool.py(5)()
-> '''
(Pdb)***名称错误:未定义名称“测试”
(Pdb)
当我向shebang添加
-m python
时,如果在脚本中运行
pdb.set_trace()
,也会发生同样的情况

这是怎么回事?

当您使用pdb(或任何其他python调试器)时,它会为调试命令获取
stdin
,这就是为什么您会得到
NameError:name“test”未定义的原因

例如,此命令将在运行时退出调试器,一次运行不会出现此错误(或交互式调试):

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


您可以使用另一个文件描述符。使用bash,您可以使用以下内容创建新的文件描述符:

exec 3<> test.txt

只要运行脚本,就可以使用test.txt作为输入,并且可以在stdin上使用stdin。如果需要,它也可以与管道一起使用。

另一个选项是创建自己的Pdb对象,并在其中设置stdin和stdout。我的概念证明涉及两个终端,但可以肯定的是,有些工作可以合并到某种非常不安全的网络服务器上

  • 创建两个先进先出:
  • 在一个终端中,在后台打开stdout,然后写入stdin:
  • 在python代码/控制台中创建pdb对象,并使用它:
  • 利润 您应该能够在第一个控制台上使用pdb

    唯一的缺点是必须使用自定义pdb,但是在init(PYTHONSTARTUP或类似)上进行一些猴子补丁可以帮助:

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

    你的控制TTY仍然是终端,对吗?使用此选项而不是
    pdb.set\u 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()
    

    在这种情况下,还没有让readline自动完成。“向上箭头”或任何其他readline细节都不起作用。

    能否更改脚本以接受来自stdin以外的文件的输入?可能是@user1901786的副本?如何在CLI脚本中访问stdin?使用
    sys.stdin
    ?另外,您是只想为此编写一个测试,还是需要在脚本中启动调试器?如果需要调试器,您希望它在哪一点与脚本结合?“对不起,这个问题对我来说有点不清楚。”保罗·斯威特。不是重复的。我要做的是获取PyCharm社区版并尝试调试它。如果您可以手动输入或粘贴输入,那么使用标准本地调试应该可以工作。如果需要调试来自管道或重定向的输入,则可能必须使用远程调试,而远程调试的设置要稍微复杂一些。虽然这解释了发生的情况,但并没有提供答案。@事实上,Swalden的“答案”是pdb坏了,从stdin获取输入很愚蠢。:/我更喜欢不需要修改工具代码的解决方案。
        cat fifo_stdout &
        cat > fifo_stdin
    
        import pdb
        mypdb=pdb.Pdb(stdin=open('fifo_stdin','r'), stdout=open('fifo_stdout','w'))
        ...
        mypdb.set_trace()
        ...
    
    import pdb
    mypdb=pdb.Pdb(stdin=open('fifo_stdin','r'), stdout=open('fifo_stdout','w'))
    pdb.set_trace=mypdb.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()