11 转发 微博 Qzone 微信 Python程序员Debug利器,和Print说再见

2023-11-05 01:30

本文主要是介绍11 转发 微博 Qzone 微信 Python程序员Debug利器,和Print说再见,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【导语】程序员每日都在和 debug 相伴。新手程序员需要学习的 debug 手段复杂多样,设置断点、查看变量值……一些网站还专门针对debug撰写了新手教程。老司机们在大型的项目中要 debug 的问题不一样,模块众多、代码超长,面对大型项目的debug之路道阻且长。针对新手和老手程序员会遇到的不同debug问题,本文推荐了两个GitHub上的开源debug工具:PySnooper 和 Behold,帮助大家更加优雅、简洁地 debug 代码。

哦对了,在分享这篇文字前,我先说一下,我这里有一份python学习资料,直接加我的python直播学习群:835017344,就能免费领取,长期真实有效。

 

前言

在之前的推荐中,营长为大家介绍过一些有趣的实用工具,包括自动化UI测试工具、代码修复神器、帮小白快速修复error、pdf翻译工具、变量命名神器等等。今天,营长要为大家推荐两个基于 Python 的 debug 工具:PySnooper 和 Behold,帮助大家对不同规模的项目,有针对性的优雅 debug。

查看变量值,是 debug 过程中常要做的一件事。Python 开发者们除了使用 print 对变量逐个输出以外,是否还有其他方法可用呢?其实,使用 Print 语句查看变量有时候也很繁琐:首先需要找到变量所在的代码行,然后注释掉部分代码,再加一行输出命令;之后再根据原步骤进行复原。这波操作在代码量较大时就要耗费大量精力了,并且如果忘记复原,或者在复原代码时出现手误,甚至可能在 debug 过程中再新加 Bug,着实不值得!

此外,在一些大型项目上,我们有时只需要对项目的部分模块或代码行进行调试,但 Python 项目调试的时候需要人工对代码进行划分,以满足调试需求,这就使 debug 变得更困难。

为了让大家更专注写代码、debug 更轻松,营长特别选取了两个 Github 的 debug 神器:PySnooper 和 Behold,分别推荐给新手和大型代码项目的老司机。

接下来,先简单介绍并比较两个工具的特性,之后再具体讲解使用步骤、功能,如果想查看工具源代码和文档,可以到文末查看,别忘了给营长点”在看“!

PySnooper 与 Behold 对比:

对象不同,简洁相同

  • 使用对象不同

两个项目有何异同?两个作者对项目的描述就能轻松发现两者的不同:PySnooper——a poor man's debugger”,针对新手程序员;Behold——为大型Python项目专门搭建的 debug 工具。

  • 安装与使用

两个工具都不约而同地把“简便易用”作为了首要目标。PySnooper 和 Behold 都是一行代码搞定:”pip install“。使用上,两者对查看变量做了针对性地改进,都支持使用一行命令输出多个变量,不同于以往使用 print 语句的方式。

  • 特性

比较而言,PySnooper 更适用于调试单个函数,对函数变量的更改过程、指向操作所在代码行上更突出,可以对变量值及值发生改变时所对应的代码行进行输出,并将输出存储为文件。而 Behold 更加注重对代码的整体调试,以及 debug 时对变量的筛选,例如支持对全局变量和局部变量的区分等。

具体而言,PySnooper 的特性包括:

  • 输出关于某个函数中变量更改的详细过程记录,包括变量的值、使变量更改的相关代码行、更改时间
  • 将上述记录输出为一个.log文件
  • 查一个或多个非局部变量的值
  • 输出调试函数所引用的函数的变量更改记录
  • 在缓存中输出记录,提高运行速度

Behold 的特性包括:

  • 简单输出一个或多个变量的改变过程
  • 依据变量的值对输出进行条件筛选
  • 对变量的输出值给予自定义标签,提高输出结果的区分度
  • 依据调试变量所在函数的所属模块筛选是否输出变量值
  • 输出对象的部分或全部属性
  • 依据全局变量和局部变量对输出进行筛选
  • 将输出存储为Pandas.Dataframe格式的数据
  • 在输出时使用自定义字典对变量输出的值进行重新定义

PySnooper: 新手程序员救星

1.安装:使用pip

pip install pysnooper

2.设置需要调试的函数:使用@pysnooper.snoop()

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

输出如下:

Starting var:.. number = 6
21:14:32.099769 call 3 @pysnooper.snoop()
21:14:32.099769 line 5 if number:
21:14:32.099769 line 6 bits = []
New var:....... bits = []
21:14:32.099769 line 7 while number:
21:14:32.099769 line 8 number, remainder = divmod(number, 2)
New var:....... remainder = 0
Modified var:.. number = 3
21:14:32.099769 line 9 bits.insert(0, remainder)
Modified var:.. bits = [0]
21:14:32.099769 line 7 while number:
21:14:32.099769 line 8 number, remainder = divmod(number, 2)
Modified var:.. number = 1
Modified var:.. remainder = 1
21:14:32.099769 line 9 bits.insert(0, remainder)
Modified var:.. bits = [1, 0]
21:14:32.099769 line 7 while number:
21:14:32.099769 line 8 number, remainder = divmod(number, 2)
Modified var:.. number = 0
21:14:32.099769 line 9 bits.insert(0, remainder)
Modified var:.. bits = [1, 1, 0]
21:14:32.099769 line 7 while number:
21:14:32.099769 line 10 return bits
21:14:32.099769 return 10 return bits

3.将上述记录输出为文件,并保存在文件夹:文件命名为file.log,保存在“/my/log/”文件夹:

@pysnooper.snoop('/my/log/file.log')

4.查看一个或多个非局部变量的值:查看foo.bar, self.whatever变量的改变过程,这两个变量不在number_to_bits函数中

@pysnooper.snoop(variables=('foo.bar', 'self.whatever'))

5.输出调试函数所引用的函数的变量更改记录:

@pysnooper.snoop(depth=2)

6.在缓存中输出记录,提高运行速度:

@pysnooper.snoop(prefix='ZZZ ')

Beholder: 针对大型Python项目的调制工具

1.安装:使用pip

pip install behold

2.简单输出一个或多个变量的改变过程:

from behold import Behold
letters = ['a', 'b', 'c', 'd', 'A', 'B', 'C', 'D']
for index, letter in enumerate(letters):# 输出效果等价于如下代码# print('index: {}, letter: {}'.format(index, letter))Behold().show('index', 'letter')

3.依据变量的值对输出进行条件筛选:

from behold import Behold
letters = ['a', 'b', 'c', 'd', 'A', 'B', 'C', 'D']
for index, letter in enumerate(letters):# 输出效果等价于如下代码# if letter.upper() == letter and index % 2 == 0:# print('index: {}'.format(index))Behold().when(letter.upper() == letter and index % 2 == 0).show('index')

4.对变量的输出值给予自定义标签,提高输出结果的区分度:这里依据变量的值分别打“even_uppercase”和“odd_losercase”标签,附在变量之后

from behold import Behold
letters = ['a', 'b', 'c', 'd', 'A', 'B', 'C', 'D']
for index, letter in enumerate(letters):# 输出效果等价于如下代码# if letter.upper() == letter and index % 2 == 0:# print('index: {}, letter:, {}, even_uppercase'.format(index, letter))# if letter.upper() != letter and index % 2 != 0:# print('index: {}, letter: {} odd_lowercase'.format(index, letter))Behold(tag='even_uppercase').when(letter.upper() == letter and index % 2 == 0).show('index', 'letter')Behold(tag='odd_lowercase').when(letter.lower() == letter and index % 2 != 0).show('index', 'letter')

5.依据调试变量所在函数的所属模块筛选是否输出变量值:

首先使用behold对函数设定调试规则:

from behold import Behold
# 这是一个在代码库中常用的自定义函数
def my_function():x = 'hello' # 这是函数本身的逻辑# 在“testing”环境时输出x的值Behold().when_context(what='testing').show('x')# 仅在“debug”环境时对函数进行调试输出if Behold().when_context(what='debugging').is_true():import pdb; pdb.set_trace()

在另一个代码模块中对设定调试规则的函数进行调试:

from behold import in_context
# 设置context为“testing”
@in_context(what='testing')
def test_x():my_function()
test_x() # 将输出'x: hello'
# 使用环境管理器设置环境为“debugging”以进行调试
with in_context(what='debugging'):my_function() # 转至pdb调试工具

6.输出对象的部分或全部属性:使用“with_args”指定调试对象的部分属性,使用“no_args”输出调试对象的全部属性

from behold import Behold, Item
item = Item(a=1, b=2, c=3)
#输出对象的部分属性
Behold(tag='with_args').show(item, 'a', 'b')
#输出对象的全部属性
Behold(tag='no_args').show(item)

7.依据全局变量和局部变量对输出进行筛选:

from __future__ import print_function
from behold import Behold, Item
# 定义全局变量
g = 'global_content'
# 定义一个函数,设定局部变量
def example_func():employee = Item(name='Toby')boss = Item(employee=employee, name='Michael')print('# Can't see global variable')Behold().show('boss', 'employee', 'g')print('
# I can see the the boss's name, but not employee name')Behold('no_employee_name').show(boss)print('
# Here is how to show global variables')Behold().show(global_g=g, boss=boss)# 可以对变量的输出顺序进行调整print('
# You can force variable ordering by supplying string arguments')Behold().show('global_g', 'boss', global_g=g, boss=boss)print('
# And a similar strategy for nested attributes')Behold().show(employee_name=boss.employee.name)
example_func()

8.将输出存储为Pandas.Dataframe格式的数据:需要对变量值的标签进行定义,标签将存储为变量的键值

from __future__ import print_function
from pprint import pprint
from behold import Behold, in_context, get_stash, clear_stash
def my_function():out = []for nn in range(5):x, y, z = nn, 2 * nn, 3 * nnout.append((x, y, z))# 对变量值的标签进行定义# 尽在测试x的环境下存储y和z的值Behold(tag='test_x').when_context(what='test_x').stash('y', 'z')# 仅在测试y的环境下存储x和z的值Behold(tag='test_y').when_context(what='test_y').stash('x', 'z')# 仅在测试z的环境下存储x和y的值Behold(tag='test_z').when_context(what='test_z').stash('x', 'y')return out
@in_context(what='test_x')
def test_x():assert(sum([t[0] for t in my_function()]) == 10)
@in_context(what='test_y')
def test_y():assert(sum([t[1] for t in my_function()]) == 20)
@in_context(what='test_z')
def test_z():assert(sum([t[2] for t in my_function()]) == 30)
test_x()
test_y()
test_z()
print('
# contents of test_x stash. Notice only y and z as expected')
pprint(get_stash('test_x'))
print('
# contents of test_y stash. Notice only x and z as expected')
pprint(get_stash('test_y'))
print('
# contents of test_z stash. Notice only x and y as expected')
print(get_stash('test_z'))

也可以对存储的结果进行清除。

clear_stash()

当该命令的参数为空时,默认清除所有调试数据的缓存。如果想要指定清除某个或某些参数的调试缓存数据,则需在参数中进行指定。

9.在输出时使用自定义字典对变量输出的值进行重新定义:

下例中对变量的值进行了自定义。假设自定义字典中的键值为数据库索引,下例展示了将该索引转变为自定义标签的方法。

from __future__ import print_function
from behold import Behold, Item
# 定义Behold的子类以支持自定义的属性提取
class CustomBehold(Behold):@classmethoddef load_state(cls):cls.name_lookup = {1: 'John',2: 'Paul',3: 'George',4: 'Ringo'}def extract(self, item, name):# 如果没有加载lookup state,则先进行加载if not hasattr(self.__class__, 'name_lookup'):self.__class__.load_state()# 抽取变量的值val = getattr(item, name)# 如果变量是一个Item类变量,则进行值转换if isinstance(item, Item) and name == 'name':return self.__class__.name_lookup.get(val, None)# 否则使用Behold默认的转换函数else:return super(CustomBehold, self).extract(item, name)
# 定义一组Item变量用于测试
items = [Item(name=nn) for nn in range(1, 5)]
print('
# Show items using standard Behold class')
for item in items:Behold().show(item)
print('
# Show items using CustomBehold class with specialized extractor')
for item in items:CustomBehold().show(item, 'name', 'instrument')

总结

在本文中,营长针对新手程序员和 Python 大型项目的代码调试为大家分别推荐了PySnooper和Behold两个调试工具,帮助大家简化代码调试过程、优化调试输出,以提高代码调试效率,希望对大家有所帮助。在未来,营长也会继续努力为大家发掘更多好用的工具,帮助大家更优雅地书写代码。

PySnooper的Github地址:https://github.com/cool-RR/PySnooper/tree/2c8c74903d20e0e52e358ce95af437a18f5fb495Behold的Github地址:https://github.com/robdmc/behold

这篇关于11 转发 微博 Qzone 微信 Python程序员Debug利器,和Print说再见的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/346470

相关文章

W外链微信推广短连接怎么做?

制作微信推广链接的难点分析 一、内容创作难度 制作微信推广链接时,首先需要创作有吸引力的内容。这不仅要求内容本身有趣、有价值,还要能够激起人们的分享欲望。对于许多企业和个人来说,尤其是那些缺乏创意和写作能力的人来说,这是制作微信推广链接的一大难点。 二、精准定位难度 微信用户群体庞大,不同用户的需求和兴趣各异。因此,制作推广链接时需要精准定位目标受众,以便更有效地吸引他们点击并分享链接

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

nudepy,一个有趣的 Python 库!

更多资料获取 📚 个人网站:ipengtao.com 大家好,今天为大家分享一个有趣的 Python 库 - nudepy。 Github地址:https://github.com/hhatto/nude.py 在图像处理和计算机视觉应用中,检测图像中的不适当内容(例如裸露图像)是一个重要的任务。nudepy 是一个基于 Python 的库,专门用于检测图像中的不适当内容。该

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip

键盘快捷键:提高工作效率与电脑操作的利器

键盘快捷键:提高工作效率与电脑操作的利器 在数字化时代,键盘快捷键成为了提高工作效率和优化电脑操作的重要工具。无论是日常办公、图像编辑、编程开发,还是游戏娱乐,掌握键盘快捷键都能带来极大的便利。本文将详细介绍键盘快捷键的概念、重要性、以及在不同应用场景中的具体应用。 什么是键盘快捷键? 键盘快捷键,也称为热键或快捷键,是指通过按下键盘上的一组键来完成特定命令或操作的方式。这些快捷键通常涉及同

HTML提交表单给python

python 代码 from flask import Flask, request, render_template, redirect, url_forapp = Flask(__name__)@app.route('/')def form():# 渲染表单页面return render_template('./index.html')@app.route('/submit_form',

uniapp设置微信小程序的交互反馈

链接:uni.showToast(OBJECT) | uni-app官网 (dcloud.net.cn) 设置操作成功的弹窗: title是我们弹窗提示的文字 showToast是我们在加载的时候进入就会弹出的提示。 2.设置失败的提示窗口和标签 icon:'error'是设置我们失败的logo 设置的文字上限是7个文字,如果需要设置的提示文字过长就需要设置icon并给