如何在ruby traceback中获取源和变量值? [英] How can I get source and variable values in ruby tracebacks?
问题描述
以下是典型的Ruby on Rails追溯的最后几帧:
应用程序跟踪http://img444.imageshack.us/img444/8990/rails-lastfew.png
Here's the last few frames of a typical Ruby on Rails traceback: application trace http://img444.imageshack.us/img444/8990/rails-lastfew.png
这里是最后几帧Python中典型的Nevow追溯:
alt text http:// img444 .imageshack.us / img444 / 9173 / nw-lastfew.png
And here are the last few frames of a typical Nevow traceback in Python: alt text http://img444.imageshack.us/img444/9173/nw-lastfew.png
这不仅仅是Web环境,你可以在ipython和irb之间进行类似的比较。如何在Ruby中获得更多的这些细节?
It's not just the web environment either, you can make similar comparisons between ipython and irb. How can I get more of these sorts of details in Ruby?
推荐答案
AFAIK曾经遇到过一个例外,抓住它提出的上下文。如果您捕获异常的新调用,可以使用evil.rb的Binding.of_caller来抓取调用范围,然后执行
AFAIK, once an exception has been caught it's too late to grab the context in which it was raised. If you trap the exception's new call, you could use evil.rb's Binding.of_caller to grab the calling scope, and do
eval("local_variables.collect { |l| [l, eval(l)] }", Binding.of_caller)
但这是一个很大的黑客。正确的答案可能是扩展Ruby以允许对调用堆栈进行一些检查。我不知道一些新的Ruby实现是否允许这样做,但我记得对Binding.of_caller的反弹,因为它会使优化更加困难。
But that's quite a big hack. The right answer is probably to extend Ruby to allow some inspection of the call stack. I'm not sure if some of the new Ruby implementations will allow this, but I do remember a backlash against Binding.of_caller because it will make optimizations much harder.
说实话,我不明白这个背景:只要翻译记录了有关优化执行的足够信息,Binding.of_caller应该能够工作,尽管也许是缓慢的。)
(To be honest, I don't understand this backlash: as long as the interpreter records enough information about the optimizations performed, Binding.of_caller should be able to work, although perhaps slowly.)
好吧,我想出来了。 Longish代码如下:
Ok, I figured it out. Longish code follows:
class Foo < Exception
attr_reader :call_binding
def initialize
# Find the calling location
expected_file, expected_line = caller(1).first.split(':')[0,2]
expected_line = expected_line.to_i
return_count = 5 # If we see more than 5 returns, stop tracing
# Start tracing until we see our caller.
set_trace_func(proc do |event, file, line, id, binding, kls|
if file == expected_file && line == expected_line
# Found it: Save the binding and stop tracing
@call_binding = binding
set_trace_func(nil)
end
if event == :return
# Seen too many returns, give up. :-(
set_trace_func(nil) if (return_count -= 1) <= 0
end
end)
end
end
class Hello
def a
x = 10
y = 20
raise Foo
end
end
class World
def b
Hello.new.a
end
end
begin World.new.b
rescue Foo => e
b = e.call_binding
puts eval("local_variables.collect {|l| [l, eval(l)]}", b).inspect
end
这篇关于如何在ruby traceback中获取源和变量值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!