断点调试和日志调试之间的平衡点 --- 函数计算调试之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 基地址相加,我们就可以得到每个局部变量的地址,获取到每个变量的内容。

相关链接

相关实践学习
基于函数计算一键部署掌上游戏机
本场景介绍如何使用阿里云计算服务命令快速搭建一个掌上游戏机。
建立 Serverless 思维
本课程包括: Serverless 应用引擎的概念, 为开发者带来的实际价值, 以及让您了解常见的 Serverless 架构模式
目录
相关文章
|
16天前
|
Serverless 应用服务中间件 开发工具
Serverless 应用引擎产品使用之阿里函数计算中,在本地进行调试,并且需要用到Docker如何解决
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
23 0
|
3天前
|
Python
【Python进阶(二)】——程序调试方法
【Python进阶(二)】——程序调试方法
|
7天前
|
监控 Python
Python中精通异常日志记录
Python中精通异常日志记录
11 0
|
14天前
|
SQL DataWorks 安全
DataWorks产品使用合集之DataWorks资源里python运行时候,查看中途打印日志如何解决
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
26 0
|
16天前
|
运维 监控 Serverless
Serverless 应用引擎产品使用之阿里函数计算中在自定义环境下用debian10运行django,用官方层的python3.9,配置好环境变量后发现自定义层的django找不到了如何解决
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
22 3
|
16天前
|
弹性计算 前端开发 Serverless
Serverless 应用引擎操作报错合集之在阿里云函数计算中,调用了FC函数但是没有执行或者报错,并且在FC函数后台也看不到调用记录日志如何解决
Serverless 应用引擎(SAE)是阿里云提供的Serverless PaaS平台,支持Spring Cloud、Dubbo、HSF等主流微服务框架,简化应用的部署、运维和弹性伸缩。在使用SAE过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
33 5
|
17天前
|
Dubbo Java Serverless
Serverless 应用引擎操作报错合集之Nacos中nacos启动正常,访问白页,启动日志显示正常如何解决
Serverless 应用引擎(SAE)是阿里云提供的Serverless PaaS平台,支持Spring Cloud、Dubbo、HSF等主流微服务框架,简化应用的部署、运维和弹性伸缩。在使用SAE过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
25 0
Serverless 应用引擎操作报错合集之Nacos中nacos启动正常,访问白页,启动日志显示正常如何解决
|
17天前
|
弹性计算 Serverless 应用服务中间件
Serverless 应用引擎操作报错合集之阿里函数计算中出现'python app.py'的错误如何解决
Serverless 应用引擎(SAE)是阿里云提供的Serverless PaaS平台,支持Spring Cloud、Dubbo、HSF等主流微服务框架,简化应用的部署、运维和弹性伸缩。在使用SAE过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
24 3
|
25天前
|
存储 API Python
python之代理ip的配置与调试
python之代理ip的配置与调试
|
27天前
|
Python
Python中的f-string记录表达式:调试文档与实践指南
【4月更文挑战第17天】Python 3.8 引入了f-string记录表达式,允许在格式化字符串时执行赋值操作。这在文档字符串和调试时尤其有用。基本语法是 `f"{variable = expression}"`。示例包括在函数文档字符串中展示变量值和在调试输出中记录变量状态。注意性能和可读性,以及赋值顺序。f-string记录表达式提升了代码效率和维护性,成为Python开发的实用工具。

热门文章

最新文章

相关产品

  • 函数计算