当前位置: 首页 > news >正文

这款 Python 调试神器推荐收藏

大家好,对于每个程序开发者来说,调试几乎是必备技能。

代码写到一半卡住了,不知道这个函数执行完的返回结果是怎样的?调试一下看看

代码运行到一半报错了,什么情况?怎么跟预期的不一样?调试一下看看

调试的方法多种多样,不同的调试方法适合不同的场景和人群。

  • 如果你是刚接触编程的小萌新,对很多工具的使用还不是很熟练,那么 print 和 log 大法好;

  • 如果你在本地(Win或者Mac)电脑上开发,那么 IDE 的图形化界面调试无疑是最适合的;

  • 如果你在服务器上排查BUG,那么使用 PDB 进行无图形界面的调试应该是首选;

  • 如果你要在本地进行开发,但是项目的进行需要依赖复杂的服务器环境,那么可以了解下 PyCharm 的远程调试;

除了以上,今天明哥再给你介绍一款非常好用的调试工具,它能在一些场景下,大幅度提高调试的效率, 那就是 PySnooper,它在 Github 上已经收到了 13k 的 star,获得大家的一致好评。

有了这个工具后,就算是小萌新也可以直接无门槛上手,从此与 print 说再见~

文章目录

    • 技术提升
    • 1. 快速安装
    • 2. 简单案例
    • 3. 详细使用
      • 2.1 重定向到日志文件
      • 2.2 跟踪非局部变量值
      • 2.3 设置跟踪函数的深度
      • 2.4 设置调试日志的前缀
      • 2.5 设置最大的输出长度
      • 2.6 支持多线程调试模式
      • 2.7 自定义对象的格式输出

技术提升

技术要学会分享、交流,不建议闭门造车。一个人走的很快、一堆人可以走的更远。

本文来自技术群粉丝的分享、推荐,资料、代码、数据、技术交流提升,均可加交流群获取,群友已超过2000人,添加时切记的备注方式为:来源+兴趣方向,方便找到志同道合的朋友。

方式①、添加微信号:pythoner666,备注:来自 CSDN + python
方式②、微信搜索公众号:Python学习与数据挖掘,后台回复:加群

1. 快速安装

执行下面这些命令进行安装 PySnooper

$ python3 -m pip install pysnooper  # 或者  
$ conda install -c conda-forge pysnooper  # 或者  
$ yay -S python-pysnooper  

2. 简单案例

下面这段代码,定义了一个 demo_func 的函数,在里面生成一个 profile 的字典变量,然后去更新它,最后返回。

代码本身没有什么实际意义,但是用来演示 PySnooper 已经足够。

import pysnooper  @pysnooper.snoop()  
def demo_func():  profile = {}  profile["name"] = "写代码的明哥"  profile["age"] = 27  profile["gender"] = "male"  return profile  def main():  profile = demo_func()  main()  

现在我使用终端命令行的方式来运行它

[root@iswbm ~]# python3 demo.py   
Source path:... demo.py  
17:52:49.624943 call         4 def demo_func():  
17:52:49.625124 line         5     profile = {}  
New var:....... profile = {}  
17:52:49.625156 line         6     profile["name"] = "写代码的明哥"  
Modified var:.. profile = {'name': '写代码的明哥'}  
17:52:49.625207 line         7     profile["age"] = 27  
Modified var:.. profile = {'name': '写代码的明哥', 'age': 27}  
17:52:49.625254 line         8     profile["gender"] = "male"  
Modified var:.. profile = {'name': '写代码的明哥', 'age': 27, 'gender': 'male'}  
17:52:49.625306 line        10     return profile  
17:52:49.625344 return      10     return profile  
Return value:.. {'name': '写代码的明哥', 'age': 27, 'gender': 'male'}  
Elapsed time: 00:00:00.000486  

可以看到 PySnooper 把函数运行的过程全部记录了下来,包括:

  • 代码的片段、行号等信息,以及每一行代码是何时调用的?

  • 函数内局部变量的值如何变化的?何时新增了变量,何时修改了变量。

  • 函数的返回值是什么?

  • 运行函数消耗了多少时间?

而作为开发者,要得到这些如此详细的调试信息,你需要做的非常简单,只要给你想要调试的函数上带上一顶帽子(装饰器) – @pysnooper.snoop() 即可。

3. 详细使用

2.1 重定向到日志文件

@pysnooper.snoop() 不加任何参数时,会默认将调试的信息输出到标准输出。

对于单次调试就能解决的 BUG ,这样没有什么问题,但是有一些 BUG 只有在特定的场景下才会出现,需要你把程序放在后面跑个一段时间才能复现。

这种情况下,你可以将调试信息重定向输出到某一日志文件中,方便追溯排查。

@pysnooper.snoop(output='/var/log/debug.log')  
def demo_func():  ...  

2.2 跟踪非局部变量值

PySnooper 是以函数为单位进行调试的,它默认只会跟踪函数体内的局部变量,若想跟踪全局变量,可以给 pysnooper.snoop() 加上 watch 参数

out = {"foo": "bar"}  @pysnooper.snoop(watch=('out["foo"]'))  
def demo_func():  ...  

如此一来,PySnooper 会在 out["foo"] 值有变化时,也将其打印出来

watch 参数,接收一个可迭代对象(可以是list 或者 tuple),里面的元素为字符串表达式,什么意思呢?看下面例子就知道了

@pysnooper.snoop(watch=('out["foo"]', 'foo.bar', 'self.foo["bar"]'))  
def demo_func():  ...  

watch 相对的,pysnooper.snoop() 还可以接收一个函数 watch_explode,表示除了这几个参数外的其他所有全局变量都监控。

@pysnooper.snoop(watch_explode=('foo', 'bar'))  
def demo_func():  ...  

2.3 设置跟踪函数的深度

当你使用 PySnooper 调试某个函数时,若该函数中还调用了其他函数,PySnooper 是不会傻傻的跟踪进去的。

如果你想继续跟踪该函数中调用的其他函数,可以通过指定 depth 参数来设置跟踪深度(不指定的话默认为 1)。

@pysnooper.snoop(depth=2)  
def demo_func():  ...  

2.4 设置调试日志的前缀

当你在使用 PySnooper 跟踪多个函数时,调试的日志会显得杂乱无章,不方便查看。

在这种情况下,PySnooper 提供了一个参数,方便你为不同的函数设置不同的标志,方便你在查看日志时进行区分。

@pysnooper.snoop(output="/var/log/debug.log", prefix="demo_func: ")  
def demo_func():  ...  

效果如下

2.5 设置最大的输出长度

默认情况下,PySnooper 输出的变量和异常信息,如果超过 100 个字符,被会截断为 100 个字符。

当然你也可以通过指定参数 进行修改

@pysnooper.snoop(max_variable_length=200def demo_func():  ...  

您也可以使用max_variable_length=None它从不截断它们。

@pysnooper.snoop(max_variable_length=Nonedef demo_func():  ...  

2.6 支持多线程调试模式

PySnooper 同样支持多线程的调试,通过设置参数 thread_info=True,它就会在日志中打印出是在哪个线程对变量进行的修改。

@pysnooper.snoop(thread_info=True)  
def demo_func():  ...  

效果如下

2.7 自定义对象的格式输出

pysnooper.snoop() 函数有一个参数是 custom_repr,它接收一个元组对象。

在这个元组里,你可以指定特定类型的对象以特定格式进行输出。

这边我举个例子。

假如我要跟踪 person 这个 Person 类型的对象,由于它不是常规的 Python 基础类型,PySnooper 是无法正常输出它的信息的。

因此我在 pysnooper.snoop() 函数中设置了 custom_repr 参数,该参数的第一个元素为 Person,第二个元素为 print_persion_obj 函数。

PySnooper 在打印对象的调试信息时,会逐个判断它是否是 Person 类型的对象,若是,就将该对象传入 print_persion_obj 函数中,由该函数来决定如何显示这个对象的信息。

class Person:pass  def print_person_obj(obj):  return f"<Person {obj.name} {obj.age} {obj.gender}>"  @pysnooper.snoop(custom_repr=(Person, print_person_obj))  
def demo_func():  ...  

完整的代码如下

import pysnooper  class Person:pass  def print_person_obj(obj):  return f"<Person {obj.name} {obj.age} {obj.gender}>"  @pysnooper.snoop(custom_repr=(Person, print_person_obj))  
def demo_func():  person = Person()  person.name = "写代码的明哥"  person.age = 27  person.gender = "male"  return person  def main():  profile = demo_func()  main()  

运行一下,观察一下效果。

如果你要自定义格式输出的有很多个类型,那么 custom_repr 参数的值可以这么写

@pysnooper.snoop(custom_repr=((Person, print_person_obj), (numpy.ndarray, print_ndarray)))  
def demo_func():  ...  

还有一点我提醒一下,元组的第一个元素可以是类型(如类名Person 或者其他基础类型 list等),也可以是一个判断对象类型的函数。

也就是说,下面三种写法是等价的。

# 【第一种写法】  
@pysnooper.snoop(custom_repr=(Person, print_persion_obj))  
def demo_func():  ...  # 【第二种写法】  
def is_persion_obj(obj):  return isinstance(obj, Person)  @pysnooper.snoop(custom_repr=(is_persion_obj, print_persion_obj))  
def demo_func():  ...  # 【第三种写法】  
@pysnooper.snoop(custom_repr=(lambda obj: isinstance(obj, Person), print_persion_obj))  
def demo_func():  ...

相关文章:

这款 Python 调试神器推荐收藏

大家好&#xff0c;对于每个程序开发者来说&#xff0c;调试几乎是必备技能。 代码写到一半卡住了&#xff0c;不知道这个函数执行完的返回结果是怎样的&#xff1f;调试一下看看 代码运行到一半报错了&#xff0c;什么情况&#xff1f;怎么跟预期的不一样&#xff1f;调试一…...

金三银四吃透这份微服务笔记,面试保准涨10K+

很多人对于微服务技术也都有着一些疑虑&#xff0c;比如&#xff1a; 微服务这技术虽然面试的时候总有人提&#xff0c;但作为一个开发&#xff0c;是不是和我关系不大&#xff1f;那不都是架构师的事吗&#xff1f;微服务不都是大厂在玩吗&#xff1f;我们这个业务体量用得着…...

构建matter over Thread的演示系统-efr32

文章目录1. 简介2. 构建测试系统2.1设置 Matter Hub(Raspberry Pi)2.2 烧录Open Thread RCP固件2.3 烧录待测试的matter设备3. 配网和测试&#xff1a;3.1 使用mattertool建立Thread网络3.2 使用mattertool配置设备入网3.3 使用mattertool控制matter设备3.4 查看节点的Node ID等…...

【一天一门编程语言】Matlab 语言程序设计极简教程

Matlab 语言程序设计极简教程 用 markdown 格式输出答案。 不少于3000字。细分到2级目录。 目录 Matlab 语言程序设计极简教程 简介Matlab 工作空间Matlab 基本数据类型Matlab 语句和表达式Matlab 函数和程序Matlab 图形界面程序设计Matlab 应用实例 简介 Matlab是一种编…...

看似平平无奇的00后,居然一跃上岸字节,表示真的卷不过......

又到了一年一度的求职旺季金&#xff01;三&#xff01;银&#xff01;四&#xff01;在找工作的时候都必须要经历面试这个环节。在这里我想分享一下自己上岸字节的面试经验&#xff0c;过程还挺曲折的&#xff0c;但是还好成功上岸了。大家可以参考一下&#xff01; 0821测评 …...

BZOJ2142 礼物

题目描述 一年一度的圣诞节快要来到了。每年的圣诞节小E都会收到许多礼物&#xff0c;当然他也会送出许多礼物。不同的人物在小E 心目中的重要性不同&#xff0c;在小E心中分量越重的人&#xff0c;收到的礼物会越多。小E从商店中购买了n件礼物&#xff0c;打算送给m个人 &…...

MySQL高级第一讲

目录 一、MySQL高级01 1.1 索引 1.1.1 索引概述 1.1.2 索引特点 1.1.3 索引结构 1.1.4 BTREE结构(B树) 1.1.5 BTREE结构(B树) 1.1.6 索引分类 1.1.7 索引语法 1.1.8 索引设计原则 1.2 视图 1.2.1 视图概述 1.2.2 创建或修改视图 1.3 存储过程和函数 1.3.1 存储过…...

前端面试常用内容——基础积累

1.清除浮动的方式有哪些&#xff1f; 高度塌陷&#xff1a;当所有的子元素浮动的时候&#xff0c;且父元素没有设置高度&#xff0c;这时候父元素就会产生高度塌陷。 清除浮动的方式&#xff1a; 1.1 给父元素单独定义高度 优点&#xff1a; 快速简单&#xff0c;代码少 缺…...

跟着《代码随想录》刷题(三)——哈希表

3.1 哈希表理论基础 哈希表理论基础 3.2 有效的字母异位词 242.有效的字母异位词 C bool isAnagram(char * s, char * t){int array[26] {0};int i 0;while (s[i]) {// 并不需要记住字符的ASCII码&#xff0c;只需要求出一个相对数值就可以了array[s[i] - a];i;}i 0;whi…...

HTML - 扫盲

文章目录1. 前言2. HTML2.1 下载 vscode3 HTML 常见标签3.1 注释标签3.2 标题标签3.3 段落标签3.4 换行标签3.5 格式化标签1. 加粗2. 倾斜3. 下划线3.6 图片标签3.7 超链接标签3.8 表格标签3.9 列表标签4. 表单标签4.1 from 标签4.2 input 标签4.3 select 标签4.4 textarea标签…...

【系统分析师之路】2022上案例分析历年真题

【系统分析师之路】2022上案例分析历年真题 【系统分析师之路】2022上案例分析历年真题【系统分析师之路】2022上案例分析历年真题2022上案例分析历年真题第一题&#xff08;25分&#xff09;2022上案例分析历年真题第二题&#xff08;25分&#xff09;2022上案例分析历年真题第…...

Python编程规范

Python编程规范 当今Python编程社区有许多关于编程规范的约定和惯例。以下是一些常见的Python编程规范&#xff1a; 1.使用有意义的命名 使用有意义的命名可以使代码更加清晰、易读、易维护。变量、函数、类和模块的命名应该能够明确传达其用途&#xff0c;而不是使用无意义…...

【Java】Spring Boot项目的创建和使用

文章目录SpringBoot的创建和使用1. 什么是Spring Boot&#xff1f;为什么要学Spring Boot&#xff1f;2. Spring Boot项目的优点3. Spring Boot 项目的创建3.1 使用idea创建3.2 接下来创建Spring Boot项目4. 项目目录介绍和运行4.1 运行项目4.2 输出内容5. 总结SpringBoot的创建…...

Malware Dev 00 - Rust vs C++ 初探

写在最前 如果你是信息安全爱好者&#xff0c;如果你想考一些证书来提升自己的能力&#xff0c;那么欢迎大家来我的 Discord 频道 Northern Bay。邀请链接在这里&#xff1a; https://discord.gg/9XvvuFq9Wb我会提供备考过程中尽可能多的帮助&#xff0c;并分享学习和实践过程…...

JavaScript HTML DOM 事件

文章目录JavaScript HTML DOM 事件对事件做出反应HTML 事件属性使用 HTML DOM 来分配事件onload 和 onunload 事件onchange 事件onmouseover 和 onmouseout 事件onmousedown、onmouseup 以及 onclick 事件JavaScript HTML DOM 事件 HTML DOM 使 JavaScript 有能力对 HTML 事件做…...

推荐算法——NCF知识总结代码实现

NCF知识总结代码实现1. NeuralCF 模型的结构1.1 回顾CF和MF1.2 NCF 模型结构1.3 NeuralCF 模型的扩展---双塔模型2. NCF代码实现2.1 tensorflow2.2 pytorchNeuralCF&#xff1a;如何用深度学习改造协同过滤&#xff1f; 随着技术的发展&#xff0c;协同过滤相比深度学习模型的…...

redis(4)String字符串

前言 Redis中有5大数据类型&#xff0c;分别是字符串String、列表List、集合Set、哈希Hash、有序集合Zset&#xff0c;本篇介绍Redis的字符串String Redis字符串 String是Redis最基本的类型&#xff0c;你可以理解成与Memcached一模一样的类型&#xff0c;一个key对应一个value…...

session一致性问题

在http访问请求中&#xff0c;web服务器会自动为同一个浏览器的访问用户自动创建唯一的session&#xff0c;提供数据存储功能。最常见的&#xff0c;会把用户的登录信息、用户信息存储在session中&#xff0c;以保持登录状态。只要用户不重启浏览器&#xff0c;每次http短连接请…...

上岸16K,薪资翻倍,在华为外包做测试是一种什么样的体验····

现在回过头看当初的决定&#xff0c;还是正确的&#xff0c;自己转行成功&#xff0c;现在进入了华为外包测试岗&#xff0c;脱离了工厂生活&#xff0c;薪资也翻了一倍不止。 我17年毕业于一个普通二本学校&#xff0c;电子信息工程学院&#xff0c;是一个很不出名的小本科。…...

django项目中如何添加自定义的django command

项目目录 1.我们自己建立的application叫做app&#xff0c;首先在这个app目录下&#xff0c;我们需要新建management目录&#xff0c;这个目录里应该包括&#xff1a;__ init__.py&#xff08;内容为空&#xff0c;用于打包&#xff09;和commands目录&#xff0c;然后在comma…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

C# 表达式和运算符(求值顺序)

求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如&#xff0c;已知表达式3*52&#xff0c;依照子表达式的求值顺序&#xff0c;有两种可能的结果&#xff0c;如图9-3所示。 如果乘法先执行&#xff0c;结果是17。如果5…...

uniapp 小程序 学习(一)

利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 &#xff1a;开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置&#xff0c;将微信开发者工具放入到Hbuilder中&#xff0c; 打开后出现 如下 bug 解…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解

进来是需要留言的&#xff0c;先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码&#xff0c;输入的<>当成字符串处理回显到页面中&#xff0c;看来只是把用户输…...