有没有办法找出哪个功能正在打印到终端?

2024-06-06 18:46:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我调试了一个非常复杂的函数(Python函数调用了来自Boosivs/Python的一些C++模块),还有一个^ {CD1>}或^ {CD2>},或者是我忘记删除的另一个类似函数(似乎没有用GRIP找到它),现在程序只打印一堆0。是否有一种方法可以告诉终端打印的是哪个函数,或者逐个删除打印语句是唯一的方法?如果有帮助的话,我正在使用FedoraLinux

谢谢


Tags: 模块方法函数程序终端语句grip函数调用
3条回答

我通常用各种形式的输出跟踪来扩充我的复杂设计。此处应用的特定项是trace_前缀。例如:

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”识别的输出,以及从给定例程或包中提取流。这很容易参数化(获取函数名);我和一个装饰师一起做的

一,。如果您的程序在多进程中运行,您需要知道哪个进程将“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}  -

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

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

如果打印是从Python进行的,那么使用精心设计的格式化程序设置logger可以帮助您精确地查看模块、行号、函数名、时间戳等

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

%(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!")

相关问题 更多 >