如何高效开发端智能算法?MNN 工作台 Python 调试详解

简介: 随着移动互联网的快速发展,人工智能在移动端上的应用越来越广泛,集团内端智能在图像识别、视频检测、数据计算等核心场景发挥着重要作用。

而在开发阶段,Python 毋庸置疑是算法进行研发的首选语言。但在移动端上,进行算法的部署、调试、验证,仍处在“刀耕火种”的时代,目前算法主要通过在代码中插入日志,验证程序的运行逻辑和结果。

经常使用Python的同学一定熟悉pdb模块,它是Python官方标准库提供的交互式代码调试器,和任何一门语言提供的调试能力一样,pdb提供了源代码行级别的设置断点、单步执行等常规调试能力,是Python开发的一个很重要的工具模块。

今天就让我们来重点分析下官方pdb模块源码,看看其调试功能的底层技术原理。

原理
从cpython源码中可以看到,pdb模块并非c实现的内置模块,而是纯Python实现和封装的模块。核心文件是pdb.py,它继承自bdb和cmd模块:

class Pdb(bdb.Bdb, cmd.Cmd):    ...

基本原理:利用cmd模块定义和实现一系列的调试命令的交互式输入,基于sys.settrace插桩跟踪代码运行的栈帧,针对不同的调试命令控制代码的运行和断点状态,并向控制台输出对应的信息。

cmd模块主要是提供一个控制台的命令交互能力,通过raw_input/readline这些阻塞的方法实现输入等待,然后将命令交给子类处理决定是否继续循环输入下去,就和他主要的方法名runloop一样。

cmd是一个常用的模块,并非为pdb专门设计的,pdb使用了cmd的框架从而实现了交互式自定义调试。

bdb提供了调试的核心框架,依赖sys.settrace进行代码的单步运行跟踪,然后分发对应的事件(call/line/return/exception)交给子类(pdb)处理。bdb的核心逻辑在对于调试命令的中断控制,比如输入一个单步运行的”s“命令,决定是否需要继续跟踪运行还是中断等待交互输入,中断到哪一帧等。

基本流程
pdb启动,当前frame绑定跟踪函数trace_dispatch

def trace_dispatch(self, frame, event, arg):
     if self.quitting:
         return # None
     if event == 'line':
         return self.dispatch_line(frame)
     if event == 'call':
         return self.dispatch_call(frame, arg)
     if event == 'return':
         return self.dispatch_return(frame, arg)
     if event == 'exception':
     ...

每一帧的不同事件的处理都会经过中断控制逻辑,主要是stop_here(line事件还会经过break_here)函数,处理后决定代码是否中断,需要中断到哪一行
如需要中断,触发子类方法user_#event,子类通过interaction实现栈帧信息更新,并在控制台打印对应的信息,然后执行cmdloop让控制台处于等待交互输入

def interaction(self, frame, traceback):
     self.setup(frame, traceback) # 当前栈、frame、local vars
     self.print_stack_entry(self.stack[self.curindex])
     self.cmdloop()
     self.forget()

用户输入调试命令如“next”并回车,首先会调用set_#命令,对stopframe、returnframe、stoplineno进行设置,它会影响中断控制`stop_here的逻辑,从而决定运行到下一帧的中断结果

def _set_stopinfo(self, stopframe, returnframe, stoplineno=0):
     self.stopframe = stopframe
     self.returnframe = returnframe
     self.quitting = 0
     # stoplineno >= 0 means: stop at line >= the stoplineno
     # stoplineno -1 means: don't stop at all
     self.stoplineno = stoplineno

对于调试过程控制类的命令,一般do_#命令都会返回1,这样本次runloop立马结束,下次运行到某一帧触发中断会再次启动runloop(见步骤3);对于信息获取类的命令,do_#命令都没有返回值,保持当前的中断状态。
代码运行到下一帧,重复步骤3

中断控制
中断控制也就是对于不同的调试命令输入后,能让代码执行到正确的位置停止,等待用户输入,比如输入”s”控制台就应该在下一个运行frame的代码处停止,而输出“c”就需要运行到下一个打断点的地方。中断控制发生在sys.settrace的每一步跟踪的中,是调试运行的核心逻辑。

pdb中主要跟踪了frame的四个事件:

line:同一个frame中的顺序执行事件
call:发生函数调用,跳到下一级的frame中,在函数第一行产生call事件
return:函数执行完最后一行(line),发生结果返回,即将跳出当前frame回到上一级frame,在函数最后一行产生return事件
exception:函数执行中发生异常,在异常行产生exception事件,然后在该行返回(return事件),接下来一级一级向上在frame中产生exception和return事件,直到回到底层frame。

它们是代码跟踪时的不同节点类型,pdb根据用户输入的调试命令,在每一步frame跟踪时都会进行中断控制,决定接下来是否中断,中断到哪一行。中断控制的主要方法是stop_here:

def stop_here(self, frame):
        # (CT) stopframe may now also be None, see dispatch_call.
        # (CT) the former test for None is therefore removed from here.
        if self.skip and \
               self.is_skipped_module(frame.f_globals.get('__name__')):
            return False


        # next
        if frame is self.stopframe:
            # stoplineno >= 0 means: stop at line >= the stoplineno
            # stoplineno -1 means: don't stop at all
            if self.stoplineno == -1:
                return False
            return frame.f_lineno >= self.stoplineno


        # step:当前只要追溯到botframe,就等待执行。
        while frame is not None and frame is not self.stopframe:
            if frame is self.botframe:
                return True
            frame = frame.f_back
        return False

调试命令大体上分两类:
过程控制:如setp、next、continue等这些执行后马上进入下阶段的代码执行
信息获取/设置:如args、p、list等获取当前信息的,也不会影响cmd状态

如果你想开发小程序或者了解更多小程序的内容,可以通过第三方专业开发平台,来帮助你实现开发需求:厦门在乎科技-专注厦门小程序开发公司、app开发、网站开发、h5小游戏开发

相关文章
|
7天前
|
数据采集 存储 JSON
Python爬虫开发:BeautifulSoup、Scrapy入门
在现代网络开发中,网络爬虫是一个非常重要的工具。它可以自动化地从网页中提取数据,并且可以用于各种用途,如数据收集、信息聚合和内容监控等。在Python中,有多个库可以用于爬虫开发,其中BeautifulSoup和Scrapy是两个非常流行的选择。本篇文章将详细介绍这两个库,并提供一个综合详细的例子,展示如何使用它们来进行网页数据爬取。
|
4天前
|
机器学习/深度学习 数据采集 数据可视化
使用Python实现深度学习模型:智能舆情监测与分析
【8月更文挑战第16天】 使用Python实现深度学习模型:智能舆情监测与分析
18 1
|
7天前
|
JavaScript 前端开发 ice
简单实用,Python代码调试利器~
简单实用,Python代码调试利器~
24 4
简单实用,Python代码调试利器~
|
6天前
|
机器学习/深度学习 传感器 自动驾驶
使用Python实现深度学习模型:智能车联网与自动驾驶
【8月更文挑战第14天】 使用Python实现深度学习模型:智能车联网与自动驾驶
26 10
|
9天前
|
机器学习/深度学习 数据采集 TensorFlow
使用Python实现深度学习模型:智能文化遗产保护与传承
【8月更文挑战第10天】 使用Python实现深度学习模型:智能文化遗产保护与传承
32 6
|
7天前
|
机器学习/深度学习 传感器 物联网
使用Python实现深度学习模型:智能物联网与智能家居
【8月更文挑战第13天】 使用Python实现深度学习模型:智能物联网与智能家居
16 2
|
7天前
|
JSON 算法 API
京东以图搜图功能API接口调用算法源码python
京东图搜接口是一款强大工具,通过上传图片即可搜索京东平台上的商品。适合电商平台、比价应用及需商品识别服务的场景。使用前需了解接口功能并注册开发者账号获取Key和Secret;准备好图片的Base64编码和AppKey;生成安全签名后,利用HTTP客户端发送POST请求至接口URL;最后解析JSON响应数据以获取商品信息。
|
5天前
|
算法 NoSQL 中间件
go语言后端开发学习(六) ——基于雪花算法生成用户ID
本文介绍了分布式ID生成中的Snowflake(雪花)算法。为解决用户ID安全性与唯一性问题,Snowflake算法生成的ID具备全局唯一性、递增性、高可用性和高性能性等特点。64位ID由符号位(固定为0)、41位时间戳、10位标识位(含数据中心与机器ID)及12位序列号组成。面对ID重复风险,可通过预分配、动态或统一分配标识位解决。Go语言实现示例展示了如何使用第三方包`sonyflake`生成ID,确保不同节点产生的ID始终唯一。
go语言后端开发学习(六) ——基于雪花算法生成用户ID
|
6天前
|
数据采集 数据挖掘 数据处理
Python爬虫开发:爬取简单的网页数据
本文详细介绍了如何使用Python爬取简单的网页数据,以掘金为例,展示了从发送HTTP请求、解析HTML文档到提取和保存数据的完整过程。通过这个示例,你可以掌握基本的网页爬取技巧,为后续的数据分析打下基础。希望本文对你有所帮助。
|
6天前
|
机器人 API 开发工具
大恒相机 - Python SDK 调试记录
大恒相机 - Python SDK 调试记录
13 1