断点调试和日志调试之间的平衡点 --- 函数计算调试之python篇

简介:

python 调试篇

很多初学者喜欢使用断点调试,方便之处是可以查到运行期各种栈内的变量值,来帮助debug。
但这一点如果脱离了IDE,其实是非常困难的。在服务器的执行过程中,更需要使用attach的方式才可能做到这点。

对于一些生产环境的错误定位,用断点调试几乎是完全不可能的。

而使用日志来做错误定位,对于一些脚本语言,尤其弱类型的语言,当你将一个变量经过多个函数传递的过程中,如果传递过程中不小心有拼写错误,只有最后使用到这个变量的地方才报出错误来,使用日志的方式要定位什么地方写错了非常困难,对于生产环境中多分支调用链极长的逻辑,更是难上加难。

本文将介绍一种结合函数堆栈,捕获栈中local变量的方式来达到快速定位bug的目的。

相对于其他runtime,python可以获取到很多运行时信息。通常来说,通过异常捕获,python 默认的traceback 给出的栈和错误信息已经能帮助开发者调试了。但时常来说,这并不是万能的,偶尔会遇到一些问题,必须加日志才能解决。但如果开发者日志加得不够细,生产环境中也很难立即重现,此时有什么好办法呢?

下面我们通过一个简单的例子来讲解如何在断点调试和日志调试中找一个平衡点定位python脚本中的bug。

def bar(c):
    x = [1,2,3,4]
    return x[c]

def foo(a, b):
    c = a + b
    bar(c)

def test():
    try:
        foo(2, 5)
    except:
        print "traceback"

假设 bar 中数组访问越界,实际的bug在c = a + b 那行,其实本应该是c = a - b,我们没有日志,此时如何定位到这个bug?

使用范例:

  • 我们先创建代码目录:
mkdir ~/sandbox/fc/traceback/python
  • 复制粘贴以下代码到 ~/sandbox/fc/traceback/python/main.py
import tracebackturbo as traceback

def bar(c):
    x = [1,2,3,4]
    return x[c]

def foo(a, b):
    c = a + b
    bar(c)

def handler(event, context):
    try:
        foo(5, 2)
    except:
        print traceback.format_exc(with_vars=True)

if __name__ == '__main__':
    handler(None, None)
  • 然后切换到 ~/sandbox/fc/traceback 目录
  • 执行 shell 命令: fcli shell,关于 fcli
  • 执行下述命令,其中 -d python 指的是当前代码所在目录 python ,而 python2.7python2.7 runtime
sbox -d python -t python2.7
pip install --target=$(pwd) tracebackturbo
  • 本地可以先做一下测试:
python main.py

测试结果:

Traceback Turbo (most recent call last):
  File "main.py", line 13, in test
    Local variables:
    foo(5, 2)
  File "main.py", line 9, in foo
    Local variables:
      a = 5
      b = 2
      c = 7
    bar(c)
  File "main.py", line 5, in bar
    Local variables:
      c = 7
      x = [1, 2, 3, 4]
    return x[c]
IndexError: list index out of range

我们可以看到栈中每个local变量都已经被print了出来,在生产环境中,我们可以在 service 上设置 logstore,将这部分错误信息输出到日志服务。

比较

我们可以比较全日志traceback 日志的优缺点:

  • 全日志

    • 优点

      • 可以隐藏敏感信息
      • 对于无报错,无异常抛出的代码也可以做有效记录
    • 缺点

      • 日志可能记录不全,线上问题调查很困难
      • 需要记录大量日志,太多的日志会导致性能低下
  • traceback 日志

    • 优点

      • 报错时可以拿到整个栈的信息,分析问题可以非常全面
      • 日志简洁,在没有报错的时候,不会有其他信息干扰
      • 由于只在报错才有日志,正常情况下只有try的开销,相对来说性能更高
    • 缺点

      • 局部变量中含有敏感信息,可能会暴露给日志查看人员

实现原理简介

接下来我们了解一下这个库的实现原理,简要提一下计算机系统运行时栈的结构:

栈结构

stack top
frame 0 (bar)
frame 1 (foo)
frame 2 (...)
...
frame n()

frame 的结构

name comment
function proto 函数信息地址
frame base frame 基地址
args 函数参数地址
ret 函数返回地址
var1 第一个局部变量的空间
var2 第二个局部变量的空间
... ...
varN 第N个局部变量空间

通常来说,各类计算机语言的 runtime 实现(实现细节及名称可能各不相同)都会包含上述信息。

function proto 结构

name comment
filename 实现文件名
line start, end 函数实现具体行
local variables 局部变量信息

每个变量包含

  • 声明行
  • 相对于frame 基地址偏移
  • 局部变量声明周期对应指令集

对于任何一个未 return 的函数,如果我们拿到了这个栈,就可以获取到栈顶的若干 frame ,找到function proto,就可以找到各个局部变量的偏移,通过 frame 基地址相加,我们就可以得到每个局部变量的地址,获取到每个变量的内容。

相关链接

相关实践学习
【玩转ComfyUI】基于函数计算一键部署AI生图平台ComfyUI
本次实验将带大家通过使用阿里云产品函数计算FC,快速使用ComfyUI实现更高质量的图像生成。
从 0 入门函数计算
在函数计算的架构中,开发者只需要编写业务代码,并监控业务运行情况就可以了。这将开发者从繁重的运维工作中解放出来,将精力投入到更有意义的开发任务上。
目录
相关文章
|
9月前
|
监控 安全 程序员
Python日志模块配置:从print到logging的优雅升级指南
从 `print` 到 `logging` 是 Python 开发的必经之路。`print` 调试简单却难维护,日志混乱、无法分级、缺乏上下文;而 `logging` 支持级别控制、多输出、结构化记录,助力项目可维护性升级。本文详解痛点、优势、迁移方案与最佳实践,助你构建专业日志系统,让程序“有记忆”。
758 0
|
存储 监控 API
【Azure App Service】分享使用Python Code获取App Service的服务器日志记录管理配置信息
本文介绍了如何通过Python代码获取App Service中“Web服务器日志记录”的配置状态。借助`azure-mgmt-web` SDK,可通过初始化`WebSiteManagementClient`对象、调用`get_configuration`方法来查看`http_logging_enabled`的值,从而判断日志记录是否启用及存储方式(关闭、存储或文件系统)。示例代码详细展示了实现步骤,并附有执行结果与官方文档参考链接,帮助开发者快速定位和解决问题。
393 22
|
API 开发工具 Python
|
监控 Shell Linux
Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
10597 2
|
存储 运维 监控
Elasticsearch Serverless 高性价比智能日志分析关键技术解读
本文解析了Elasticsearch Serverless在智能日志分析领域的关键技术、优势及应用价值。
1267 8
Elasticsearch Serverless 高性价比智能日志分析关键技术解读
|
SQL 分布式计算 Serverless
基于阿里云 EMR Serverless Spark 版快速搭建OSS日志分析应用
基于阿里云 EMR Serverless Spark 版快速搭建OSS日志分析应用
405 0
|
Java 程序员 应用服务中间件
「测试线排查的一些经验-中篇」&& 调试日志实战
「测试线排查的一些经验-中篇」&& 调试日志实战
336 1
「测试线排查的一些经验-中篇」&& 调试日志实战
|
前端开发 数据处理 Android开发
Flutter前端开发中的调试技巧与工具使用方法,涵盖调试的重要性、基本技巧如打印日志与断点调试、常用调试工具如Android Studio/VS Code调试器和Flutter Inspector的介绍
本文深入探讨了Flutter前端开发中的调试技巧与工具使用方法,涵盖调试的重要性、基本技巧如打印日志与断点调试、常用调试工具如Android Studio/VS Code调试器和Flutter Inspector的介绍,以及具体操作步骤、常见问题解决、高级调试技巧、团队协作中的调试应用和未来发展趋势,旨在帮助开发者提高调试效率,提升应用质量。
754 8
|
存储 Prometheus 监控
Docker容器内进行应用调试与故障排除的方法与技巧,包括使用日志、进入容器检查、利用监控工具及检查配置等,旨在帮助用户有效应对应用部署中的挑战,确保应用稳定运行
本文深入探讨了在Docker容器内进行应用调试与故障排除的方法与技巧,包括使用日志、进入容器检查、利用监控工具及检查配置等,旨在帮助用户有效应对应用部署中的挑战,确保应用稳定运行。
695 5
|
监控 数据挖掘 数据安全/隐私保护
Python脚本:自动化下载视频的日志记录
Python脚本:自动化下载视频的日志记录

相关产品

  • 函数计算
  • 推荐镜像

    更多