【问题标题】:Is there a way to find out which function is printing to the terminal?有没有办法找出正在打印到终端的功能?
【发布时间】:2020-11-26 04:08:35
【问题描述】:

我正在调试一个非常复杂的函数(从 Boost/Python 调用一些 C++ 模块的 python 函数),并且有一个 print 或 cout 或另一个我忘记删除的类似函数(似乎找不到用grep),现在程序只是不断地打印一堆0。有没有办法判断哪个函数正在打印到终端,或者是一个一个删除打印语句的唯一方法?如果有帮助,我在 Fedora linux 上

谢谢

【问题讨论】:

  • 提示:向您认为导致它打印一堆零的函数或范围添加一些调试。

标签: python linux debugging printing terminal


【解决方案1】:

我通常使用各种形式的输出跟踪来扩充我的复杂设计。此处适用的特定项目是 trace_prefix。例如:

TRACE = True
# TRACE = False    # Uncomment this line for production runs.

def func(param):
    trace_prefix = "TRACE func" if TRACE else ""
    if TRACE:
        print("ENTER", func, "param =", param)

    ...
    print(trace_prefix, func_data)
    ...

这会产生我可以通过“grep TRACE”识别的输出,以及从给定例程或包中挑选出的流。这很容易参数化(获取函数名称);我已经用装饰器完成了。

【讨论】:

  • 谢谢!我最终使用了这个和注释大部分代码的组合
【解决方案2】:

如果从 Python 进行打印,使用精细的格式化程序设置记录器可以帮助您精确查看模块、行号、函数名称、时间戳等。

这是我在项目中使用的示例格式化程序。

%(asctime)-s.%(msecs)03d %(levelname)-6.6s %(filename)-18.18s line:%(lineno)-4.4d %(funcName)-18s %(message)s

结果:

2020-08-05 00:28:36.232 DEBUG  connectionpool.py  line:0959 _new_conn          The fancy thing that gets printed.
2020-08-05 00:28:38.177 DEBUG  connectionpool.py  line:0437 _make_request      This is your message but you have more info before this.
2020-08-05 00:28:38.180 DEBUG  item.py            line:0159 start_indexing     Loggers with proper formatters can help you see
2020-08-05 00:28:38.180 DEBUG  indexer.py         line:0036 start              Extensive information

代码:

import logging
import sys

LOGGER = logging.getLogger(__name__)
HANDLER = logging.StreamHandler(sys.stdout)
HANDLER.setFormatter(logging.Formatter("%(asctime)-s.%(msecs)03d %(levelname)-6.6s %(filename)-18.18s line:%(lineno)-4.4d %(funcName)-18s %(message)s"))
LOGGER.addHandler(HANDLER)

LOGGER.error("Here we go!")

【讨论】:

    【解决方案3】:

    1。如果你的程序在多进程中运行,你需要知道哪个进程将“0”写入终端。

    #!/usr/bin/env python3
    '''
    a simple program to stimulate writing terminal in multiple processes.
    '''
    prog name: ttywriter.py
    import time
    import sys
    import multiprocessing
    def print_stderr(s):
        sys.stderr.write(f'{s}\n')
    
    while True:
        print("I'm writing to my terminal")
        p = multiprocessing.Process(target=print_stderr,args=("I am a CPP program, writing to termianl",))
        p.start()
        time.sleep(1)
    

    伪终端通常作为文件描述符1和2打开​​。你可以strace他们。

    # tty
    /dev/pts/0
    
    # ps -ef
    UID          PID    PPID  C STIME TTY          TIME CMD
    root        2640    2427  0 07:07 pts/0    00:00:00 python3 ./ttywriter.py
    
    # lsof -p `pgrep -f ttywriter` | grep pts
    python3 2640 root    0u   CHR  136,0      0t0     3 /dev/pts/0
    python3 2640 root    1u   CHR  136,0      0t0     3 /dev/pts/0
    python3 2640 root    2u   CHR  136,0      0t0     3 /dev/pts/0
    
    # strace -s 65536 -e trace=write -e write=1,2 -fp `pgrep -f ttywriter`
    strace: Process 2640 attached
    write(1, "I'm writing to my terminal\n", 27) = 27
     | 00000  49 27 6d 20 77 72 69 74  69 6e 67 20 74 6f 20 6d  I'm writing to m |
     | 00010  79 20 74 65 72 6d 69 6e  61 6c 0a                 y terminal.      |
    strace: Process 2695 attached
    [pid  2695] write(2, "I am a CPP program, writing to termianl\n", 40) = 40
     | 00000  49 20 61 6d 20 61 20 43  50 50 20 70 72 6f 67 72  I am a CPP progr |
     | 00010  61 6d 2c 20 77 72 69 74  69 6e 67 20 74 6f 20 74  am, writing to t |
     | 00020  65 72 6d 69 61 6e 6c 0a                           ermianl.         |
    [pid  2695] +++ exited with 0 +++
    --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2695, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
    

    2。如果是Python,可以hijack sys.out or print打印调用栈。

    3。如果是C/C++,可以set a conditional breakpoint for a specific string being written to terminal。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-06
      • 1970-01-01
      • 1970-01-01
      • 2020-12-17
      相关资源
      最近更新 更多