社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

一文带您了解PySnooper:让码农告别Python print函数

新语数据故事汇 • 9 月前 • 283 次点击  

在我们之前的文章《一文带您了解IceCream:码农的Python代码调试神器,告别print()》,我们介绍了IceCream替代print进行代码调试的示例。今天,受到粉丝推荐的启发,我们将介绍另一个类似的Python代码调试包:PySnooper。

在编程过程中,调试通常是一项痛苦的任务,而使用传统的print语句进行调试往往更加繁琐。为了摆脱这种痛点,我们将直接介绍PySnooper,一款强大的代码调试工具。

我们首先看看PySnooper 官方介绍:https://github.com/cool-RR/PySnooper

PySnooper:再也不用为调试而使用print了

PySnooper是一个简易的调试工具。如果你曾经使用过Bash,它就像是Python的set -x命令,只不过更加高级。

你的情景:你试图弄清楚为什么你的Python代码不按照你预期的那样工作。你很想使用一个带有断点和监视功能的完整调试器,但是你现在懒得设置一个。

你想知道哪些代码行在运行,哪些没有运行,以及本地变量的值是什么。

大多数人会在关键位置使用print语句,其中一些显示变量的值。

PySnooper让你可以做同样的事情,但是你不需要精心编写正确的print语句,只需要在你感兴趣的函数上添加一个装饰器。你将得到你的函数的逐步日志,包括哪些行运行了以及何时运行,以及本地变量何时发生了变化。

PySnooper的独特之处在于什么?你可以在你那些糟糕、庞大的企业代码库中使用它,而无需进行任何设置。只需将装饰器添加到函数上,并将输出重定向到一个专用的日志文件,指定其路径作为第一个参数即可。

安装PySnooper

pip install pysnooper

第一个示例

我们正在编写一个将数字转换为二进制的函数,通过返回一个位列表来完成。让我们通过添加@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 bits else: return [0]
number_to_bits(6)

如果你不想追踪整个函数,你可以将相关部分包装在一个with块中:

import pysnooperimport random
def foo(): lst = [] for i in range(10): lst.append(random.randrange(1, 1000))
with pysnooper.snoop(): lower = min(lst) upper = max(lst) mid = (lower + upper) / 2 print(lower, mid, upper)
foo()

PySnooper特性

PySnooper拥有许多功能,使其成为调试Python代码的一款多才多艺且实用的工具。以下是一些您应该了解和使用的顶级特性:

  • 定制PySnooper的输出。您可以通过在装饰器中使用不同的参数来定制PySnooper的输出,例如depth、prefix、file、watch等。例如,您可以使用depth来限制PySnooper跟踪的嵌套调用数量,或者使用watch来添加您想要监视的表达式。您可以在文档中找到参数的完整列表和描述。

  • 在任何Python代码、环境或框架中使用PySnooper。您可以在任何Python代码中使用PySnooper,包括第三方库、模块和包。您还可以在任何Python环境中使用它,例如Jupyter笔记本、脚本或交互式shell。您还可以在任何Python框架中使用PySnooper,例如Django、Flask、PyTorch、TensorFlow、PyTest、PyInstaller、PyGame、NumPy、Pandas、Scrapy、Matplotlib、SQLAlchemy等等。

  • 在多线程、多进程或异步代码中使用PySnooper。您可以通过在装饰器中使用thread_info或process_info参数来使用PySnooper调试多线程或多进程代码。这将在输出中添加线程或进程ID,以便您区分不同的线程或进程。您还可以使用PySnooper调试异步代码,只需使用@pysnooper.snoop_async()装饰器,而不是常规的装饰器。这将与任何异步框架一起使用,例如asyncio、trio或curio。

  • 在lambda函数、生成器、推导式和其他复杂表达式中使用PySnooper。您可以通过使用pysnooper.snoop函数而不是装饰器来调试lambda函数、生成器、推导式和其他复杂表达式。这将返回一个包装函数,您可以使用与原始函数相同的参数调用它。

像这样调试一个lambda函数:

import pysnooper
squared = pysnooper.snoop()(lambda x: x ** 2)squared(5)

将日志输出到文件:

import pysnooper
@pysnooper.snoop('file.log')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)

设置环境变量PYSNOOPER_DISABLED 为1 ,关闭debug 输出:

import osos.environ['PYSNOOPER_DISABLED'] = '1'
import pysnooper
@pysnooper.snoop()def factorial(n): if n == 1: return 1 else: return n * factorial(n - 1)
factorial(5)

以一个前缀开头,方便使用grep查找所有的snoop行:

import pysnooper
@pysnooper.snoop(prefix='SNB ')def factorial(n): if n == 1: return 1 else: return n * factorial(n - 1)
factorial(5)

删除所有与机器相关的数据(路径、时间戳、内存地址),以便轻松地与其他跟踪进行比较:

import pysnooper
@pysnooper.snoop(normalize=True)def factorial(n): if n == 1: return 1 else: return n * factorial(n - 1)
factorial(5)

PySnooper的优势

PySnooper拥有许多优势,使其成为调试Python代码的绝佳工具。以下是其中一些:

  • PySnooper易于使用,无需设置或配置。您只需要导入它,并在您想要调试的函数或方法上添加一个装饰器。您无需学习任何命令或语法,也无需以任何方式修改您的代码。

  • PySnooper速度快且轻量级。它不会减慢您的代码,也不会增加任何额外的开销。它只会打印出您调试代码所需的相关信息,而不会多余打印。

  • PySnooper灵活且可定制。您可以通过在装饰器中使用不同的参数来调整PySnooper的输出,例如depth、prefix、file、watch等。您还可以在任何Python代码、环境或框架中使用PySnooper,包括多线程、多进程和异步代码。

  • PySnooper具有教育性和趣味性。它可以帮助您了解您的代码如何工作,找到错误,优化性能,并从其他人的代码中学习。它还可以使调试更加愉快,减少沮丧感,因为它向您展示了代码背后的魔力。

PySnooper是一款强大的Python代码调试工具,易于使用且无需配置。它能快速精准地定位问题,定制输出内容,并适用于各种Python环境和框架。通过添加装饰器,您可以轻松监视函数执行情况,而无需繁琐的print语句。PySnooper的灵活性和教育性使得调试变得更加高效愉快,为开发者提供了更好的调试体验。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/167751
 
283 次点击