各语言的内建调试工具

我向来把调试工作放在编程环节的首位,因此当使用一门新的语言开始实际项目时,就愿意花精力摸索它的调试工具的使用。当了解到几门调试工具以后,发现大部分的地方是相通的。

现代 IDE 天然自带图形化的调试工具,例如 PyCharm 调试 Python. 但这篇文章并不关注于此,反而只列举命令行下的调试方案。诚然,IDE 是好用的,如果你用 IDE 开发你的主项目,并且熟悉它,就应该使用 IDE 提供的调试方案。但这并不代表你不该了解本文中的内容,至少有以下原因:

  1. IDE 太重了,而你想要有一个轻量级的调试方案。
  2. 如果你接触了一门新在函数栈中往上一层语言,你势必不想一开始就陷入 IDE 方面的问题。
  3. 有时候你进入一个新环境,而它没有提供你想要的 IDE 的选项,本文的方案就可以作为一个备选。

我认为,调试工具主要关注三方面的能力(排名有先后):

  1. 断点调试
  2. 分步迭代
  3. 监视器

所以,再轻量的工具,也势必要从以上三方面进行考察。如果工具提供的命令过于复杂,没关系,搞清楚这三个再说。

本文将考察主流脚本语言的调试工具,它们是 Python、Ruby、NodeJS. 我说过,在调试工具方面,大部分的理念是相通的。所以我将在 Python 一节详细介绍,Ruby、NodeJS 一节简略介绍对位命令。

Python

Python 内建了调试工具,可以在代码的任何位置打断点。首先,在代码中引入 Python 的调试工具:

from pdb import set_trace

然后,在你想要打断的位置,调用 set_trace 方法:

a = 1
set_trace()
b = a + 1

当程序执行到第二行代码的地方,就会在这个位置中断,进入一个交互式的命令行环境。你可以在这个环境下执行很多的命令。

首先,可以在这个环境下使用print命令查看变量的值。例如我想要看变量 a 的值,只需输入:

print(a)

实际上,print 只是 Python 的一个函数,你可以在该环境下调用任何的 Python 语句。

接下来,通过一些分步迭代的命令,我可以逐步地控制程序的运行。分步迭代的命令包括:

  • n(ext):执行到下一行的位置
  • s(tep):步进到下一个的位置
  • u(p):函数栈中的指针往上一层
  • d(own):函数栈中的指针往下一层

以上命令的括号标记用以指示别名,例如 next 命令,nnext 调用均可。

如果结束了当前的调试,需要程序继续运行,调用 c(ont(inue)) 命令(支持三种写法:ccontcontinue)。它会让程序继续运行,直到遇到下一个 set_trace() 的地方中断。

遗憾的是,我并没有在 Python 的 pdb 工具包中发现监视器的内容。好在作为优先级排在第三位的需求,少了它还是可以工作的。

Ruby

Ruby 语言也有类似的工具,Ruby 语言可以使用 pry 起到断点调试的效果。

首先,安装 pry

$ gem install pry

然后,在代码中引入 pry,需要断点的位置调用 binding.pry 方法即可:

require 'pry'

a = 1
binding.pry
b = a + 1

pry 本身没有提供分步迭代的能力,另一款工具 byebug 支持分步迭代。但是 byebug 的交互式环境没有 pry 友好,其不支持语法高亮,并失去一些优化的特性。好在有人将 prybyebug 的能力结合起来,创造了 pry-byebug,兼具两者的优点。

我建议,直接安装 pry-byebug

$ gem install pry-byebug

引入和打断点的方式不变。但已经支持从 byebug 那里借来的分步迭代的能力,分步迭代的命令包括:

  • next
  • step
  • up
  • down

注意,没有缩略的别名,你需要完完整整地输入 next 命令才能达到效果。

从断点处的恢复执行的命令同样是:continue.

pry 支持监视器的能力,对位的命令是 watch. 下面是一个简单的计算 1 到 100 的加法的 Ruby 代码:

s = 0
binding.pry
(1..100).each do |i|
  s += i
  binding.pry
end

在第一个断点处,执行命令 watch s,即可达到监视变量 s 的效果。监视器的作用是这样的,一旦监视的变量发生了改变,它会主动在控制台显示变量的值以示提醒。但 pry 有一个小脾气,你不 Enter 它不显示,它只会在命令行键入 Enter 键以后触发 watch 显示机制。

在以上的代码中,如果我们希望在每一次变量 s 加上 i 之后查看 s 的变化,需要重复调用下面两个命令:

  • continue
  • (这是键盘上的一个按键)

NodeJS

Node 环境下也有一样的基于命令行的调试工具。与 Python 和 Ruby 不同的是,它不是通过引入模块和调用方法的方式设置中断环境的,而是通过 debugger 这个关键字。

在 Node 中设置中断环境,需要做两步操作。

  1. 在代码中用 debugger 关键字:

    a = 1
    debugger
    b = a + 1
  2. 调用的时候使用 node inspect source.js 命令。

程序会在代码的最开始处停住,需要调用 continue 命令(可简写为 ccont)才会开始执行。调用 continue 命令之后,程序会持续执行,知道遇到 debugger 的位置。这时候,就可以停下来好好欣赏程序的环境了。

停在 debugger 位置时,进入的是一个命令环境。此时输入 repl 命令进入一个调试环境,在这个环境下可以输入变量的名称以及表达式显示它们的值。一旦调试表达式结束,输入 Ctrl + C 退出调试环境回到命令环境。

如果你觉得切换调试环境和命令环境较为繁琐,有一些轻量级的方法用以受限的场景。如果你只想查看变量 sum 的值,或者表达式 a+1 的值,可借助 exec 命令:

debug> exec sum
debug> exec a + 1

调试器支持分步迭代和监视器,命令列举如下:

  • next
  • step
  • out
  • watch

值得一提的是,没有了 updown 命令,取而代之的是 out. out 的意思是执行完当前函数的内容,回到上一层调用该函数的位置。

你可能感兴趣的:(调试,调试器,调试工具,编程语言)