debugging 在Python中记录函数的每一行的便捷方式,不会使代码混乱

rfbsl7qr  于 2023-01-13  发布在  Python
关注(0)|答案(2)|浏览(144)

假设我有一个令人讨厌的函数,里面有很多if-else,这个函数有一个随机发生的bug。
我无法重现或调试它,我想添加一些日志记录,以查看当错误再次发生时,函数的哪些部分已经执行。
现在可以在每一行之前添加一个日志,如下所示:

def my_annoying_function(self):
    logger.info("self._call_other_function()")
    self._call_other_function()
    logger.info("self.myvar = 5")
    self.myvar = 5
    logger.info("i = 4")
    i = 4
    logger.info("i = i + 5")
    i = i + 5
    if self.myothervar is True:
        logger.info("self.call_other_function2()")
        self.call_other_function2()
    ...

有没有人知道一种方法来实现相同的日志记录行为,并在执行之前或之后记录每个语句,而不会使代码混乱?

mnemlml8

mnemlml81#

若要向另一个答案添加详细信息,可以通过编程方式打开跟踪,如下例所示:

import sys
import trace

def func3():
    pass

def func1():
    func3()

def func4():
    pass

def func2():
    func4()

def func(two):
    if two:
        func2()
    else:
        func1()

def func_call():
    func(False)
    func(True)

def main():
    print('Hello, world! This is Python %s' % sys.version)
    t = trace.Trace()
    t.run(func_call.__code__)

if __name__ == '__main__':
    main()

运行时,将打印:

$ python main.py 
Hello, world! This is Python 3.11.0 (main, Oct 24 2022, 17:48:40) [GCC 11.3.0]
 --- modulename: main, funcname: func_call
main.py(29):     func(False)
 --- modulename: main, funcname: func
main.py(22):     if two:
main.py(25):         func1()
 --- modulename: main, funcname: func1
main.py(10):     func3()
 --- modulename: main, funcname: func3
main.py(6):     pass
main.py(30):     func(True)
 --- modulename: main, funcname: func
main.py(22):     if two:
main.py(23):         func2()
 --- modulename: main, funcname: func2
main.py(18):     func4()
 --- modulename: main, funcname: func4
main.py(14):     pass

因此,它跟踪在Trace.run中指定的函数内部以及在该调用内部执行的所有语句。

zbq4xfa0

zbq4xfa02#

我认为python -m trace --trace demo.py值得一试。

# demo.py
def is_prime(n):
    if n == 1:
        return False
    for i in range(2, n):
        if n % i == 0:
            return False
    return True

def print_all_prime(_min, _max):
    for i in range(_min, _max+1):
        if is_prime(i):
            print(i)

if __name__ == '__main__':
    print_all_prime(1, 10)

python -m trace --trace demo.py输出为

--- modulename: demo, funcname: <module>
demo.py(1): def is_prime(n):
demo.py(9): def print_all_prime(_min, _max):
demo.py(14): if __name__ == '__main__':
demo.py(15):     print_all_prime(1, 10)
 --- modulename: demo, funcname: print_all_prime
demo.py(10):     for i in range(_min, _max+1):
demo.py(11):         if is_prime(i):
 --- modulename: demo, funcname: is_prime
demo.py(2):     if n == 1:
demo.py(3):         return False
demo.py(10):     for i in range(_min, _max+1):
demo.py(11):         if is_prime(i):
 --- modulename: demo, funcname: is_prime
demo.py(2):     if n == 1:
demo.py(4):     for i in range(2, n):
demo.py(7):     return True
demo.py(12):             print(i)
2
demo.py(10):     for i in range(_min, _max+1):
demo.py(11):         if is_prime(i):
 --- modulename: demo, funcname: is_prime
demo.py(2):     if n == 1:
demo.py(4):     for i in range(2, n):
demo.py(5):         if n % i == 0:
demo.py(4):     for i in range(2, n):
demo.py(7):     return True
demo.py(12):             print(i)
3
demo.py(10):     for i in range(_min, _max+1):
demo.py(11):         if is_prime(i):
 --- modulename: demo, funcname: is_prime
demo.py(2):     if n == 1:
demo.py(4):     for i in range(2, n):
demo.py(5):         if n % i == 0:
demo.py(6):             return False
demo.py(10):     for i in range(_min, _max+1):
demo.py(11):         if is_prime(i):
 --- modulename: demo, funcname: is_prime
demo.py(2):     if n == 1:
demo.py(4):     for i in range(2, n):
demo.py(5):         if n % i == 0:
demo.py(4):     for i in range(2, n):
demo.py(5):         if n % i == 0:
demo.py(4):     for i in range(2, n):
demo.py(5):         if n % i == 0:
demo.py(4):     for i in range(2, n):
demo.py(7):     return True
demo.py(12):             print(i)
5
demo.py(10):     for i in range(_min, _max+1):
demo.py(11):         if is_prime(i):
 --- modulename: demo, funcname: is_prime
demo.py(2):     if n == 1:
demo.py(4):     for i in range(2, n):
demo.py(5):         if n % i == 0:
demo.py(6):             return False
demo.py(10):     for i in range(_min, _max+1):
demo.py(11):         if is_prime(i):
 --- modulename: demo, funcname: is_prime
demo.py(2):     if n == 1:
demo.py(4):     for i in range(2, n):
demo.py(5):         if n % i == 0:
demo.py(4):     for i in range(2, n):
demo.py(5):         if n % i == 0:
demo.py(4):     for i in range(2, n):
demo.py(5):         if n % i == 0:
demo.py(4):     for i in range(2, n):
demo.py(5):         if n % i == 0:
demo.py(4):     for i in range(2, n):
demo.py(5):         if n % i == 0:
demo.py(4):     for i in range(2, n):
demo.py(7):     return True
demo.py(12):             print(i)
7
demo.py(10):     for i in range(_min, _max+1):
demo.py(11):         if is_prime(i):
 --- modulename: demo, funcname: is_prime
demo.py(2):     if n == 1:
demo.py(4):     for i in range(2, n):
demo.py(5):         if n % i == 0:
demo.py(6):             return False
demo.py(10):     for i in range(_min, _max+1):
demo.py(11):         if is_prime(i):
 --- modulename: demo, funcname: is_prime
demo.py(2):     if n == 1:
demo.py(4):     for i in range(2, n):
demo.py(5):         if n % i == 0:
demo.py(4):     for i in range(2, n):
demo.py(5):         if n % i == 0:
demo.py(6):             return False
demo.py(10):     for i in range(_min, _max+1):
demo.py(11):         if is_prime(i):
 --- modulename: demo, funcname: is_prime
demo.py(2):     if n == 1:
demo.py(4):     for i in range(2, n):
demo.py(5):         if n % i == 0:
demo.py(6):             return False
demo.py(10):     for i in range(_min, _max+1):

相关问题