iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >怎么在Python调试过程中设置不中断的断点
  • 114
分享到

怎么在Python调试过程中设置不中断的断点

2023-06-16 13:06:35 114人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

这篇文章主要介绍“怎么在python调试过程中设置不中断的断点”,在日常操作中,相信很多人在怎么在Python调试过程中设置不中断的断点问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么在Python调试过程

这篇文章主要介绍“怎么在python调试过程中设置不中断的断点”,在日常操作中,相信很多人在怎么在Python调试过程中设置不中断的断点问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么在Python调试过程中设置不中断的断点”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

Python 调试器的心脏:sys.set_trace

在诸多可选的 Python 调试器中,使用最广泛的三个是:

  • pdb,它是 Python 标准库的一部分

  • PyDev,它是内嵌在 Eclipse 和 PyCharm 等 IDE 中的调试器

  • ipdb,它是 IPython 的调试器

Python 调试器的选择虽多,但它们几乎都基于同一个函数:sys.settrace。 值得一提的是, sys.settrace 可能也是 Python 标准库中最复杂的函数。

怎么在Python调试过程中设置不中断的断点

简单来讲,settrace 的作用是为解释器注册一个跟踪函数,它在下列四种情形发生时被调用:

  • 函数调用

  • 语句执行

  • 函数返回

  • 异常抛出

一个简单的跟踪函数看上去大概是这样:

def simple_tracer(frame, event, arg):  co = frame.f_code  func_name = co.co_name  line_no = frame.f_lineno  print("{e} {f} {l}".fORMat(e=event, f=func_name, l=line_no))  return simple_tracer

在分析函数时我们首先关注的是参数和返回值,该跟踪函数的参数分别是:

  • frame,当前堆栈帧,它是包含当前函数执行时解释器里完整状态的对象

  • event,事件,它是一个值可能为 calllinereturn 或 exception字符串

  • arg,参数,它的取值基于 event 的类型,是一个可选项

该跟踪函数的返回值是它自身,这是由于解释器需要持续跟踪两类跟踪函数:

  • 全局跟踪函数(每线程):该跟踪函数由当前线程调用 sys.settrace 来设置,并在解释器创建一个新的堆栈帧时被调用(即代码中发生函数调用时)。虽然没有现成的方式来为不同的线程设置跟踪函数,但你可以调用 threading.settrace 来为所有新创建的 threading 模块线程设置跟踪函数。

  • 局部跟踪函数(每一帧):解释器将该跟踪函数的值设置为全局跟踪函数创建帧时的返回值。同样也没有现成的方法能够在帧被创建时自动设置局部跟踪函数。

该机制的目的是让调试器对被跟踪的帧有更精确的把握,以减少对性能的影响。

简单三步构建调试器 (我们最初的设想)

仅仅依靠上文提到的内容,用自制的跟踪函数来构建一个真正的调试器似乎有些不切实际。幸运的是,Python 的标准调试器 pdb 是基于 Bdb 构建的,后者是 Python 标准库中专门用于构建调试器的基类。

基于 Bdb 的简易断点调试器看上去是这样的:

import bdbimport inspect class Debugger(bdb.Bdb):  def __init__(self):      Bdb.__init__(self)      self.breakpoints = dict()      self.set_trace() def set_breakpoint(self, filename, lineno, method):  self.set_break(filename, lineno)  try :      self.breakpoints[(filename, lineno)].add(method)  except KeyError:      self.breakpoints[(filename, lineno)] = [method] def user_line(self, frame):  if not self.break_here(frame):      return   # Get filename and lineno from frame  (filename, lineno, _, _, _) = inspect.getframeinfo(frame)   methods = self.breakpoints[(filename, lineno)]  for method in methods:      method(frame)

这个调试器类的全部构成是:

  1. 继承 Bdb,定义一个简单的构造函数来初始化基类,并开始跟踪。

  2. 添加 set_breakpoint 方法,它使用 Bdb 来设置断点,并跟踪这些断点。

  3. 重载 Bdb 在当前用户行调用的 user_line 方法,该方法一定被一个断点调用,之后获取该断点的源位置,并调用已注册的断点。

这个简易的 Bdb 调试器效率如何呢?

Rookout 的目标是在生产级性能的使用场景下提供接近普通调试器的使用体验。那么,让我们来看看先前构建出来的简易调试器表现的如何。

为了衡量调试器的整体性能开销,我们使用如下两个简单的函数来进行测试,它们分别在不同的情景下执行了 1600 万次。请注意,在所有情景下断点都不会被执行。

def empty_method():   pass def simple_method():   a = 1   b = 2   c = 3   d = 4   e = 5   f = 6   g = 7   h = 8   i = 9   j = 10

在使用调试器的情况下需要大量的时间才能完成测试。糟糕的结果指明了,这个简陋 Bdb 调试器的性能还远不足以在生产环境中使用。

怎么在Python调试过程中设置不中断的断点

对调试器进行优化

降低调试器的额外开销主要有三种方法:

  1. 尽可能的限制局部跟踪:由于每一行代码都可能包含大量事件,局部跟踪比全局跟踪的开销要大得多。

  2. 优化 call 事件并尽快将控制权还给解释器:在 call 事件发生时调试器的主要工作是判断是否需要对该事件进行跟踪。

  3. 优化 line 事件并尽快将控制权还给解释器:在 line 事件发生时调试器的主要工作是判断我们在此处是否需要设置一个断点。

于是我们复刻了 Bdb 项目,精简特征、简化代码,针对使用场景进行优化。这些工作虽然得到了一些效果,但仍无法满足我们的需求。因此我们又继续进行了其它的尝试,将代码优化并迁移至 .pyx 使用 Cython 进行编译,可惜结果(如下图所示)依旧不够理想。最终,我们在深入了解 CPython 源码之后意识到,让跟踪过程快到满足生产需求是不可能的。

怎么在Python调试过程中设置不中断的断点

放弃 Bdb 转而尝试字节码操作

熬过先前对标准调试方法进行的试验-失败-再试验循环所带来的失望,我们将目光转向另一种选择:字节码操作。

Python 解释器的工作主要分为两个阶段:

  1. 将 Python 源码编译成 Python 字节码:这种(对人类而言)不可读的格式专为执行的效率而优化,它们通常缓存在我们熟知的 .pyc 文件当中。

  2. 遍历 解释器循环中的字节码: 在这一步中解释器会逐条的执行指令。

我们选择的模式是:使用字节码操作来设置没有全局额外开销的不中断断点。这种方式的实现首先需要在内存中的字节码里找到我们感兴趣的部分,然后在该部分的相关机器指令前插入一个函数调用。如此一来,解释器无需任何额外的工作即可实现我们的不中断断点。

这种方法并不依靠魔法来实现,让我们简要地举个例子。

首先定义一个简单的函数:

def multiply(a, b):   result = a * b   return result

在 inspect 模块(其包含了许多实用的单元)的文档里,我们得知可以通过访问 multiply.func_code.co_code 来获取函数的字节码:

'|\x00\x00|\x01\x00\x14}\x02\x00|\x02\x00S'

使用 Python 标准库中的 dis 模块可以翻译这些不可读的字符串。调用 dis.dis(multiply.func_code.co_code) 之后,我们就可以得到:

  4          0 LOAD_FAST               0 (a)             3 LOAD_FAST               1 (b)             6 BINARY_MULTIPLY                 7 STORE_FAST              2 (result)   5         10 LOAD_FAST               2 (result)            13 RETURN_VALUE

到此,关于“怎么在Python调试过程中设置不中断的断点”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: 怎么在Python调试过程中设置不中断的断点

本文链接: https://www.lsjlt.com/news/283918.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么在Python调试过程中设置不中断的断点
    这篇文章主要介绍“怎么在Python调试过程中设置不中断的断点”,在日常操作中,相信很多人在怎么在Python调试过程中设置不中断的断点问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么在Python调试过程...
    99+
    2023-06-16
  • python调试 设置断点
    1在所需要调试的地方加入如下代码:    import pdb    pdb.set_trace() 2调试代码常用命令:     实例请见参考文...
    99+
    2023-01-31
    断点 python
  • 如何在Eclipse中设置断点调试
    这篇文章给大家介绍如何在Eclipse中设置断点调试,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1  Debug视图1.1 线程堆栈视图  线程堆栈视图表示当前线程的堆栈,从中可以看出在...
    99+
    2023-05-31
    eclipse 中设置
  • IDEA中怎么设置断点进行调试
    这篇文章主要介绍“IDEA中怎么设置断点进行调试”,在日常操作中,相信很多人在IDEA中怎么设置断点进行调试问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”IDEA中怎么设置断点进行调试”的疑惑有所帮助!接下来...
    99+
    2023-06-04
  • php怎么设置断点调试
    PHP是一种常用的服务器端编程语言,随着互联网技术的快速发展,PHP的应用越来越广泛。但是,当我们开发PHP的时候,难免会遇到各种问题和错误,这时候如何调试会成为我们需要解决的问题之一。本文将介绍如何设置断点调试PHP代码,帮助您快速定位和...
    99+
    2023-05-14
    断点调试 php
  • pycharm怎么设置断点调试
    断点调试是逐步执行代码的一种方式,有助于识别错误和问题,可在 pycharm 中通过以下方式设置断点:单击代码行号或按 f9 键在当前行设置断点;从 debug 工具栏中使用 "togg...
    99+
    2024-04-04
    macos pycharm
  • 怎么在VSCode中断点调试CMake工程
    怎么在VSCode中断点调试CMake工程?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。初始状态假设我们已经有一个CMake工程项目(比如从github上直接下...
    99+
    2023-06-08
  • Navicat中怎么设置SQL查询的断点和调试
    Navicat并不支持SQL查询的断点和调试功能。Navicat是一个数据库管理工具,主要用于连接、管理和操作数据库,而不是用于编写...
    99+
    2024-05-10
    Navicat
  • pycharm如何设置断点调试程序
    在 pycharm 中设置断点调试程序需要以下步骤:添加断点:在代码行单击鼠标左键,然后选择 "toggle breakpoint"。启动调试器:选择 "run" > "debug...
    99+
    2024-04-18
    pycharm
  • 怎么在Python中利用pdb设置断点
    怎么在Python中利用pdb设置断点?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Python主要用来做什么Python主要应用于:1、Web开发;2、数据科学研究;3、网络...
    99+
    2023-06-14
  • 如何浅析Visual Studio调试中断点的设置
    本篇文章给大家分享的是有关如何浅析Visual Studio调试中断点的设置,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。我曾经问过很多人,你一般是怎么调试你的程序的?F9, ...
    99+
    2023-06-17
  • JavaScript中F12调试器、debugger设置断点的示例分析
    这篇文章主要介绍JavaScript中F12调试器、debugger设置断点的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完! JavaScript中F12调试器,debug...
    99+
    2024-04-02
  • pycharm中debug断点调试的示例分析
    这篇文章将为大家详细讲解有关pycharm中debug断点调试的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1.操作步骤:1.1 添加断点直接在标记处点击鼠标左键即可。(删除断点只需再点击断点处...
    99+
    2023-06-14
  • IDEA中怎么设置和管理断点
    在IDEA中设置和管理断点可以帮助开发者更有效地调试代码。以下是在IDEA中设置和管理断点的步骤: 在代码编辑器中找到想要设置断点...
    99+
    2024-04-03
    IDEA
  • vue中的代码如何进行断点调试
    目录vue代码进行断点调试下面开始调试总结vue代码进行断点调试 对于这样的代码,我们打两个断点,想要调试的话,需要在项目根目录,新建一个文件:vue.config.js,然后根据...
    99+
    2023-05-17
    vue代码 vue代码断点调试 vue断点调试
  • C#中怎么判断点的位置
    本篇文章为大家展示了C#中怎么判断点的位置,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。C#判断点的位置方法一public int isLeft(Point ...
    99+
    2023-06-17
  • 怎么设置JavaScript代码的断点
    这篇文章主要介绍“怎么设置JavaScript代码的断点”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么设置JavaScript代码的断点”文章能帮助大家解决问题...
    99+
    2024-04-02
  • python怎么判断元素在不在数组中
    可以使用in和not in操作符来判断元素在不在数组中。例如,假设有一个数组arr,我们想要判断元素x是否在数组中,可以使用以下代码...
    99+
    2023-09-05
    python
  • 在win10环境下的vscode中使用xdebug进行PHP断点调试
    第一步、下载VScode和phpstudy 具体下载网址我放到下面 VScode:Visual Studio Code - Code Editing. RedefinedVisual Studio Code - Code Editing. ...
    99+
    2023-09-02
    vscode php 断点调试
  • 怎么在python中中断Break语句
    这期内容当中小编将会给大家带来有关怎么在python中中断Break语句,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Python的优点有哪些1、简单易用,与C/C++、Java、C# 等传统语言相比,P...
    99+
    2023-06-14
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作