디버그 코드를 인쇄 출력을 사용하지 마십시오

저자 : 품질 관리 튜링 연구소 연구원의 장청, 텐센트 상호 엔터테인먼트

| 리드는 최근 인쇄를 파괴 할 수있는 시간 디버그 알려진 GitHub의에 파이썬 PySnooper의 디버그 유물을 잘립니다있다. 그래서 도구를 무엇 장점, 어떻게 아직이 도구를 사용합니다. 이 논문은 장점과 단점 및 도구의 사용을 설명합니다.

디버그 코드를 인쇄 출력을 사용하지 마십시오


서문 :

사용 파이썬 개발 프로세스는 항상 디버그를 피할 수 없습니다. 기존의 디버깅 과정은 크게 두 가지 유형으로 구분됩니다

a) 단일 단계 디버깅 중단 +.

중단이 예상 스테핑 +하면 가장 많이 사용하고, 큰 프로젝트에 대한 프로세스가 약이다 : 먼저 축소 될 인쇄의 값을 분석하여, 플러스 인쇄 문 중요한 코드의 위치,이 프로세스가 걸릴 수 있습니다 인쇄 법을 이용하여, 여러 번, 일반적으로 기능 모듈의보다 완전한 범위로 감소 될 수 있으며, 그 모듈 버그의 핵심은 단일 단계 디버깅으로 중단 한 후 브레이크 포인트를 표시 발생할 수있는 각을 볼 변수의 정확한 값은, 코드의 특정 라인에 따른 위치 오차 변수의 최종 값은 마지막으로 수정.

b) PDB 디버깅.

PDB 파이썬 가방을 싣고, 소스 레벨 디버깅 파이썬 대화식 프로그램은, 메인 기능 설정 중단 단일 단계 디버깅을 포함하는, 디버그 기능은 변수를 동적으로, 스택 세그먼트 찾고 변경, 현재 코드 뷰 입력 값 등등. PDB 디버깅 프로세스 1) 거의 모든 같은, 특정 방법 당신은 웹 검색을 사용할 수 있습니다.

기존의 디버깅 프로세스의 단점은 :

A) 원래 코드를 변경 코드에 print 문을 추가해야합니다;

나) 과정을 통해 중단 점 및 단일 단계는 필요성이 지속적으로 초점을 유지하기 위해, 한 번 중요한 점은 처음부터 다시 시작됩니다 건너 뜁니다.

최근 GitHub의에 디버그 도구를 잘립니다, 당신은 기존의 디버깅 프로세스의 단점을 해결할 수 있습니다. 여기에서 모양과이 마법 도구를 사용합니다.

1. PySnooper는 무엇인가

디버그 코드를 인쇄 출력을 사용하지 마십시오


이 도구의 사용 형태는 로그의 형태로 파일에 인쇄 기능의 작동 중에 장식하는 현재 코드 실행 시간에 각 변수의 값을 기록하고 실행하는 실행 코드의 라인. 변수의 변화에 ​​따르면 문제를 찾을 수 있습니다. 개인적으로 도구를 시도하면 다음과 같은 장점을 요약 될 수있다 :

1、无需为了查看变量的值,使用print打印变量的值,从而修改了原有的代码。

2、接口的运行过程以日志的形式保存,方便随时查看。

3、可以根据需要,设置函数调用的函数的层数,方便将注意力集中在需要重点关注的代码段。

4、多个函数的日志,可以设置日志前缀表示进行标识,方便查看时过滤。

该工具有这么多优点,那么如何使用呢,下面结合demo来介绍该工具的使用。

2. 使用方式介绍

1. 工具安装

pip install pysnooper

2. 官方demo介绍

官方demo代码:

import pysnooper
@pysnooper.snoop()
def number_to_bits(number):
 if number:
 bits = []
 while number:
 number, remainder = divmod(number, 2)
 bits.insert(0, remainder)
 return bits
 else:
 return [0]
number_to_bits(6)

控制台输出:

디버그 코드를 인쇄 출력을 사용하지 마십시오


控制台的输出如上图,从图中可以看到,从进入到函数开始,会记录每一行代码的执行及记录新增局部变量或已有局部变量的变化,直到函数结束。以装饰器的形式使用该工具后,会将函数运行的中间结果打印出来,这样方便后续的bug定位和分析。

3. 参数介绍

以装饰器的形式使用该工具,其包含了四个参数,参数包括output, variables, depth, prefix,如下图。

디버그 코드를 인쇄 출력을 사용하지 마십시오


1、output参数。该参数指定函数运行过程中产生的中间结果的保存位置,若该值为空,则将中间结果输出到控制台。

2、variables参数。该参数是vector类型, 因为在默认情况下,装饰器只跟踪局部变量,要跟踪非局部变量,则可以通过该字段来指定。默认值为空vector。

3、depth参数。该参数表示需要追踪的函数调用的深度。在很多时候,我们在函数中会调用其他函数,通过该参数就可以指定跟踪调用函数的深度。默认值为1。

4、prefix参数。该参数用于指定该函数接口的中间结果前缀。当多个函数都使用的该装饰器后,会将这些函数调用的中间结果保存到一个文件中,此时就可以通过前缀过滤不同函数调用的中间结果。默认值为空字符串。

3. 工具应用

要使用该工具只需要理解该装饰器(snoop)的参数的含义,下面结合几个demo介绍参数的使用及对结果的影响。

1. output 参数使用

若使用默认参数,则将中间结果输出到控制台,若填写该参数,则将中间结果写入到该参数指定的目录下,如运行以下代码,其中间结果会保存在装饰器snoop中设置日志保存的路径中,注意这里不会自动创建目录,所以需要事先创建目录,如测试代码中填写路径后需要创建log目录。

测试代码:

import pysnooper
def add(num1, num2):
 return num1 + num2
@pysnooper.snoop("./log/debug.log", prefix="--*--")
def multiplication(num1, num2):
 sum_value = 0
 for i in range(0, num1):
 sum_value = add(sum_value, num2)
 return sum_value
value = multiplication(3, 4)

运行该代码后,在./log/debug.log的内容如下:

디버그 코드를 인쇄 출력을 사용하지 마십시오


从运行代码的中间结果中可以看出,文件中记录了各行代码的执行过程及局部变量的变化。在debug时,通过分析该文件,就可以跟踪每一步的执行过程及局部变量的变化,这样就能快速的定位问题所在;由于运行的中间结果保存在文件中,方便随时分析其运行的中间结果,也便于共享。

2. variables参数使用

在默认参数的情况下,使用该工具只能查看局变量的变化过程,当需要查看局部变量以外变量时,则可以通过variables参数进行设置,比如下方代码,在Foo类型,需要查看类实例的变量self.num1, self.num2, self.sum_value,则可以看将该变量设置当参数传入snoop的装饰器中。

测试代码:

import pysnooper
class Foo(object):
 def __init__(self):
 self.num1 = 0
 self.num2 = 0
 self.sum_value = 0
 def add(self, num1, num2):
 return num1 + num2
 @pysnooper.snoop(output="./log/debug.log", variables=("self.num1", "self.num2", "self.sum_value"))
 def multiplication(self, num1, num2):
 self.num1 = num1
 self.num2 = num2
 sum_value = 0
 for i in range(0, num1):
 sum_value = self.add(sum_value, num2)
 self.sum_value = sum_value
 return sum_value
foo = Foo()
foo.multiplication(3, 4)

为了体现该参数的作用,这里分别使用默认参数和上述参数(代码中设置的参数)运行代码,得到的结果如下:

디버그 코드를 인쇄 출력을 사용하지 마십시오

使用默认参数的结果


디버그 코드를 인쇄 출력을 사용하지 마십시오

使用代码中参数的结果

从两个中间结果中可以看出,若变量不是局部变量,哪怕在函数中使用了该变量,如果不显示设置打印该变量的中间结果,则不会将该变量的中间结果打印到文件中。

3. depth参数使用

该参数用来指定记录函数调用层数的结果,默认值为1,若要查看多层函数调用的中间结果,则可将该参数设置为>=2。

测试代码:

import pysnooper
def add(num1, num2):
 return num1 + num2
@pysnooper.snoop("./log/debug.log", depth=2)
def multiplication(num1, num2):
 sum_value = 0
 for i in range(0, num1):
 sum_value = add(sum_value, num2)
 return sum_value
value = multiplication(3, 4)

为了对比,将depth的值分别设置为1和2,其结果如下:

디버그 코드를 인쇄 출력을 사용하지 마십시오

depth=1的结果


디버그 코드를 인쇄 출력을 사용하지 마십시오

depth=2的结果

从上述结果中可以看出,若要查看更深层次函数调用的情况,则可以通过设置depth值进行查看。这样方便用户有选择性的查看函数的调用情况。

4. prefix参数使用

该参数主要用于设置中间结果的前缀,这样就可以区分不同的函数调用的中间结果,默认参数为""。

测试代码:

import pysnooper
def add(num1, num2):
 return num1 + num2
@pysnooper.snoop("./log/debug.log", prefix="--*--")
def multiplication(num1, num2):
 sum_value = 0
 for i in range(0, num1):
 sum_value = add(sum_value, num2)
 return sum_value
value = multiplication(3, 4)

运行代码后的中间结果如下:

디버그 코드를 인쇄 출력을 사용하지 마십시오


从结果中可以看到,中间结果的每一行都包含了prefix设置的前缀,这样便于区分不同的函数调用的中间结果。

上述的介绍为了将注意力集中到具体的参数,采取设置单一参数的形式进行介绍(output+其他单个参数)。在实际使用时,可以同时设置多个参数。使用PySnooper工具来记录函数运行的中间结果,比起传统的使用断点+单步调试,pdb等调试方法,PySnooper工具有着巨大的优势。

4. 该工具的不足之处

虽然使用debug在使用PySnooper很方便,但还是存在一些问题(以4月26号拉取代码为依据),比如:

1、无法很好的支持递归调用。

2、调用每个函数的中间结果只能保存在一个文件中,如果需要区分不同文件的结果,需要使用prefix来进行前缀标识。

3、对于跨文件函数调用,不支持记录调用函数所在的文件名。

当然PySnooper是最近在github上火起来的项目,还不够完善是正常的,相信这些不足之处后续也会得到完善,期待一个更好的PySnooper。

5. 总结

이 문서는 PpySnooper 도구 설명이 도구는 먼저 기존의 디버깅 방법에 비해 장점이며, 매개 변수와 도구의 데모의 역할의 매개 변수에 대한 설명을 설명 무엇을 소개했다. 도구의 마지막 단점.

참고 :

https://mp.weixin.qq.com/s/QayverYLWv5dU38RFYK6Ew

https://github.com/cool-RR/PySnooper


추천

출처blog.51cto.com/13591395/2401949