【问题标题】:Use pdb.set_trace() in a script that reads stdin via a pipe在通过管道读取标准输入的脚本中使用 pdb.set_trace()
【发布时间】:2012-02-29 00:40:38
【问题描述】:

我有一个通过管道读取标准输入的 python 脚本,但我似乎无法将它与 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()

假设 tempfile.csv 是一个有两行的文件,

$ cat tempfile.csv 
line1
line2

然后我可以运行我的脚本: $ 猫临时文件.csv | ./my_script.py,一切都很好:

$ cat tempfile.csv | ./my_script.py 
Printing a line:  line1

Printing a line:  line2

另一方面,如果我将 pdb.set_trace() 放在任何地方,则会出现错误。例如,将 pdb.set_trace() 放在 def main() 下面,然后我得到 ​​p>

$ 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

请注意,我的问题可能与 this question 有关(即 pdb 默认从标准输入读取),但我需要更多帮助。

【问题讨论】:

    标签: python


    【解决方案1】:

    这是一个对我有用的例子:

    import sys
    import pdb
    
    lines = sys.stdin.readlines()
    sys.stdin = open("/dev/tty")
    pdb.set_trace()
    

    编辑:从3.7开始你不再需要为set_trace导入pdb,它可以作为breakpoint使用,所以上面只需要一个sys导入。

    import sys
    
    lines = sys.stdin.readlines()
    sys.stdin = open("/dev/tty")
    breakpoint()
    

    您可能希望将上面的sys.stdin.readlines() 替换为可迭代的fileinput.input()(如果sys.argv[1:] 中的文件列表为空,则将defaults 替换为sys.stdin),如下所示:

    import fileinput
    import sys
    
    lines = fileinput.input()
    sys.stdin = open("/dev/tty")
    breakpoint()
    

    【讨论】:

    • 我遇到了同样的问题,效果很好。有人知道为什么吗?
    • pdb 从 stdin 读取以进行交互;因此,要使用 pdb,您必须首先读取所有标准输入,然后将标准输入设置为电传打字接口,或者换句话说,将其连接回您的终端和键盘而不是 shell 管道。此时您可以像平常一样启动 pdb(并使用它)
    • 我用过:import sys; sys.stdin = open('/dev/tty'); import pdb; pdb.set_trace()
    • 对我不起作用,我得到site-packages/prompt_toolkit/application/application.py", line 654, in _run_async2 assert not self._is_running AssertionError,然后在它崩溃后我的终端无法使用
    • 我撒了个谎——ipdb 会发生这种情况,但pdb 可以正常工作
    【解决方案2】:

    问题是:cat 不会停止发送数据,因为您的脚本当前正在调试。当你要跟踪时,cat + 你的键盘仍然会填充标准输入。您需要选择其中之一。

    可以读取整个stdin,然后set_trace()就不会被stdin填充了:

    sys.stdin.read()
    pdb.set_trace()
    

    【讨论】:

    • 这似乎有帮助,但并不完全。我把 sys.stdin.read() 放在几个地方,pdb.set_trace() 放在下面,我不再得到NameError。但是,pdb 没有打开......它只是退出(与上面相同的消息,没有 NameError)
    【解决方案3】:

    使用ripdb 模块 (pip install ripdb) 为我解决了这个问题。

    【讨论】:

      【解决方案4】:

      为了完整起见,我根据接受的答案使用以下代码制作了一个 sn-p。

      import sys; sys.stdin = open('/dev/tty'); import pdb; pdb.set_trace();
      

      【讨论】:

        【解决方案5】:

        你可能想看看 Celery RDB (Remote Debugger) contrib 模块是如何工作的:

        https://github.com/celery/celery/blob/master/celery/contrib/rdb.py

        它似乎涉及很多流处理,但我已经对其进行了测试,它通过允许您远程登录到新的本地网络端口来工作。这不是更好的 ipdb,而是简单的 pdb。

        【讨论】:

          【解决方案6】:

          我今天遇到了这个确切的问题。我发现Winpdb 工作得很好。

          【讨论】:

          • 这种情况下如何调用winpdb?
          猜你喜欢
          • 2015-01-18
          • 2011-04-29
          • 2011-03-12
          • 1970-01-01
          • 2015-10-08
          • 2013-11-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多