我从互联网上复制了下面的 Ruby 代码,并做了一些修改,但是没有用。
我可以做什么来自己调试程序?
只要有可能就打印出变量(这叫做 printf 调试)
STDERR.puts x.inspect
或者
STDERR.puts "Variable x is #{x.inspect}"
如果您想使输入变得更容易,那么您可能需要使用 样本 gem。
打开警告。如果你正在运行 ruby,然后运行它与 -w开关(例如 ruby -w script.rb)。如果您从 irb 运行它,并且使用的是1.9.2之前的 Ruby 版本,那么在会话开始时键入 $VERBOSE = true。如果你拼错了实例变量,一旦警告出现,你将得到
ruby
-w
ruby -w script.rb
$VERBOSE = true
警告: 实例变量 @valeus未初始化
@valeus
理解二进制印章的概念(以下引用来自 敏捷开发者的实践)
将问题空间分成两半,看看哪一半包含问题。然后再把那一半分成两半,重复。
如果你成功地使用了二进制印章,你可能会发现有一行并没有完成你期望它完成的任务。比如说
[1, 2, 3].include?([1,2])
给出一个值 false,即使你认为它会返回 true。在这种情况下,您可能需要查看文档。文档的网站包括 Ruby-doc.org或 APIDock。在后一种情况下,你可以在靠近右上角的放大镜旁边输入 include?,选择下面有 Array的 include?(如果你不知道 [1, 2, 3]是什么类,在 irb 中输入 [1, 2, 3].class) ,然后你就可以输入 包括? (数组),它描述了它的功能。
false
true
include?
Array
[1, 2, 3]
[1, 2, 3].class
但是,如果文档没有帮助,那么如果您可以问一个问题,即某一行为什么没有做它应该做的事情,而不是为什么整个脚本没有做它应该做的事情,那么您更有可能得到一个好的答案。
在 Ruby 中:
ruby -rdebug myscript.rb
那么,
n(ext)
s(tep)
c(ontinue)
p(uts)
(像 perl debug)
在 Rails 中: 用以下命令启动服务器
script/server --debugger
并在代码中添加 debugger。
debugger
所有调试器之母是普通的旧打印屏幕。大多数时候,你可能只想检查一些简单的物品,一个快速简单的方法是这样的:
@result = fetch_result p "--------------------------" p @result
这将把@result 的内容打印到 STDOUT,并在前面加一行,以便于识别。
如果你使用像 Rails 这样的自动加载/重载框架,你甚至不需要重新启动你的应用程序。(除非由于框架特定的设置而没有重新加载正在调试的代码)
我发现90% 的用例都是这样的。您也可以使用 ruby-debug,但是我发现它大多数时候都是过度使用。
使用 窥探(GitHub)。
安装:
$ gem install pry $ pry
然后加上:
require 'pry'; binding.pry
进入你的程序。
但是,在 pry0.12.2中,没有像 next、 break等这样的导航命令。其他一些 gem 还提供了这个功能,例如 pry-byebug。
pry
next
break
pry-byebug
所有其他的答案已经给出了几乎所有的东西... 只是一点点补充。
如果您想要更多类 IDE 的调试器(非 CLI) ,并且不害怕使用 Vim 作为编辑器,我建议使用 Vim Ruby Debugger插件。
它的文档非常简单,请点击链接查看。简而言之,它允许您在编辑器的当前行上设置断点,在暂停时在漂亮的窗口中查看本地变量,单步执行(step over/into)ーー几乎所有常见的调试器特性。
对我来说,使用这个 vim 调试器来调试一个 Rails 应用程序是非常愉快的,尽管 Rails 的 丰富的记录能力几乎消除了对它的需要。
根据栏杆的建议: 使用撬! 我只能同意这一点。
窥探比 IRB 好得多。
你得加上
require 'pry'
你的源文件 然后在源代码中插入断点
binding.pry
在你想看东西的地方 (这就像在经典的 IDE 环境中触发断点一样)
一旦你的程序触发了
你会被直接扔进监听室, 手边有你们节目的全部内容, 这样你就可以简单地探索周围的一切,研究所有的物体, 更改状态,甚至动态更改代码。
我相信你不能改变你现在使用的方法的代码, 所以很遗憾你不能改变下一行要执行的内容。 但是好的 Ruby 代码往往是单行的; -)
Printf 调试
调试技术一直存在争议, 有些人喜欢使用 print 语句进行调试, 还有一些人喜欢用调试器深入挖掘。
我建议你两种方法都试试。
事实上,一个 Unix 的老前辈最近说过, 在某些时候 printf 调试对他来说是更快的方法。
但是,如果您在某个工作中是新手,并且需要理解大量代码, 那么穿过这里真的很有用, 到处设置断点, 顺其自然。
它应该可以让您了解代码是如何编织的。
如果你对其他人的软件是新手, 也许能帮你穿过那里。
你很快就会知道他们是不是巧妙地安排了, 或者那只是一堆狗屎。
我强烈推荐这个视频,以便选择适当的工具,目前调试我们的代码。
Https://www.youtube.com/watch?v=gwgf8gcynv0
就我个人而言,我会在这个视频中强调两大主题。
这就是我的意见!
我刚刚发现了这个 gem (将 Pry 变成了 MRI Ruby 2.0 + 的调试器)
Https://github.com/deivid-rodriguez/pry-byebug
gem install pry-byebug
然后使用与 pry完全相同的方法,在你想要中断的线上标记:
然而,与香草撬不同的是,这个 gem 有一些类似于 GDB 的关键导航命令,比如 next、 step和 break:
step
break SomeClass#run # Break at the start of `SomeClass#run`. break Foo#bar if baz? # Break at `Foo#bar` only if `baz?`. break app/models/user.rb:15 # Break at line 15 in user.rb. break 14 # Break at line 14 in the current file.
通过引发异常 进行调试比仔细查看 print日志语句要好,而且对于大多数 bug 来说,它通常比打开像 pry或 byebug这样的 irb 调试器要好。这些工具不应该总是你的第一步。
print
byebug
Exception
.inspect
调试 Ruby (特别是 Rails)代码的 最快方法是在调用方法或对象(例如 foo)上的 .inspect时,沿着代码的执行路径调用 raise:
foo
raise
raise foo.inspect
在上面的代码中,raise触发一个 Exception,该 停止代码的执行返回一个错误消息,该错误消息方便地包含了在您试图调试的行上关于对象/方法(即 foo)的 .inspect信息。
这种技术对于 快点检查对象或方法(是 nil吗?)以及立即确认一行代码是否在给定的上下文中执行非常有用。
nil
只有在您了解了代码执行流的状态之后,您才应该考虑转移到像 pry或 byebug这样的 ruby gem irb 调试器,在这里您可以更深入地研究执行路径中对象的状态。
当您试图调试一个问题时,好的建议是始终: 阅读!@# $ing 错误消息(RTFM)
这意味着在操作之前读取错误消息 小心点和 彻底的,这样当你调试时,在读取错误消息时问下面的心理问题 按这个顺序:
在堆栈跟踪中,要特别注意来自项目的代码行(例如,如果使用 Rails,以 app/...开头的行)。99% 的情况下,问题都出在您自己的代码上。
app/...
为了说明为什么翻译 按这个顺序很重要..。
您执行的代码在某些时候也是这样执行的:
@foo = Foo.new ... @foo.bar
你会得到一个错误:
undefined method "bar" for Nil:nilClass
初学者看到这个错误,认为问题在于方法 bar是 未定义。在这个错误中,真正重要的部分是:
bar
for Nil:nilClass
for Nil:nilClass意味着 @foo是零!@foo不是 Foo实例变量!有一个对象是 Nil。当您看到这个错误时,只是 Ruby 试图告诉您类 Nil的对象的方法 bar不存在。(当然!因为我们试图为类 Foo的一个对象而不是 Nil使用一个方法)。
@foo
Foo
Nil
不幸的是,由于这个错误是如何编写的(undefined method "bar" for Nil:nilClass) ,它很容易被欺骗,以为这个错误与 bar是 undefined有关。如果不仔细阅读,这个错误会导致初学者错误地深入研究 Foo上的 bar方法的细节,完全忽略错误提示对象属于错误类(在本例中为 nil)的部分。通过完整地读取错误消息,很容易避免这种错误。
undefined
摘要:
在开始任何调试之前都要小心地使用 读取 < em > whole 错误消息。这意味着: 始终在错误消息 第一中检查对象的 类别类型,然后检查它的 方法、 之前,开始侦查任何你认为可能发生错误的堆栈跟踪或代码行。这5秒钟可以帮你节省5个小时的沮丧。
不要关注打印日志: 引发异常或者使用 irb 调试器。在调试之前仔细阅读错误以避免兔子洞。
要轻松调试 Ruby shell 脚本,只需将其第一行改为:
#!/usr/bin/env ruby
致:
#!/usr/bin/env ruby -rdebug
然后,每次显示调试器控制台时,您都可以选择:
c
n
cat
h
参见: 使用 ruby-debug 进行调试,Ruby-debug gem 的关键快捷方式。
如果脚本只是 挂起来,你需要一个回溯,尝试使用 lldb/gdb,比如:
lldb
gdb
echo 'call (void)rb_backtrace()' | lldb -p $(pgrep -nf ruby)
然后检查你的过程前景。
如果效果更好的话,用 gdb代替 lldb。前缀用 sudo来调试非自有进程。
sudo
Ruby 标准 lib 有一个类似 gdb 的易用控制台调试器: Http://ruby-doc.org/stdlib-2.1.0/libdoc/debug/rdoc/debugger__.html 不需要安装任何额外的 gem。 Rails 脚本也可以这样调试。
例如:。
def say(word) require 'debug' puts word end
从 Ruby 2.4.0开始,在任何 Ruby 程序的中间启动 IRB REPL 会话都变得更加容易。将这些代码行放在程序中要调试的位置:
require 'irb' binding.irb
您可以运行 Ruby 代码并打印出本地变量。键入 Ctrl + D 或 quit结束 REPL 并让 Ruby 程序继续运行。
quit
您还可以使用 puts和 p在程序运行时从程序中打印出值。
puts
p
删除所有的东西
欢迎来到2017 ^ _ ^
好的,如果您不反对尝试新的 IDE,那么可以为 自由执行以下操作。
{workspaceRoot}
launch.json
"cwd"
"program"
"showDebuggerOutput"
"debug.allowBreakpointsEverywhere": true
vscode
View->Extensions
.vscode
{ “版本”: “0.2.0” “配置”: [ { “名称”: “调试本地文件”, “ type”“ Ruby” “请求”“发射” “ cwd”: “ ${ workspaceRoot }”, “ program”: “{ workspaceRoot }/. ./script _ name. rb”, “ args”: [] , “ showDebuggerOutput”: true } ] }
File->Preferences->Settings
Debug
"debug.allowBreakpointsEverywhere"
在做完所有这些有趣的事情之后,你应该能够在一个菜单中设置断点和调试,这个菜单与2017年中期类似,并且有一个更黑暗的主题: < img src = “ https://i.stack.imgur.com/1zCb2.jpg”alt = “ enter image description here”> < img src = “ https://i.stack.imgur.com/1zCb2.jpg”alt = “ enter image description here”> 和所有有趣的东西,比如你的调用堆栈,变量查看器,等等。
最大的 PITA 是1)安装前置要求和2)记住配置 .vscode\launch.json文件。只有 # 2应该为未来的项目添加任何负担,您只需复制一个足够通用的配置,就像上面列出的那样。可能有一个更通用的配置位置,但我不知道我的头顶。
.vscode\launch.json
有许多具有不同特性的调试器,您可以根据这些特性进行选择。我对 多管闲事感到满意的优先事项是:
如果您使用的是 RubyMine,那么调试 Ruby 脚本是简单而直接的。
假设您有一个 Ruby 脚本 hello _ world. rb
在第6行设置一个断点,如下所示。
现在可以启动调试器来运行脚本:
然后,当执行命中一个断点时,您就可以检查变量,等等。