这是典型的Ruby on Rails回溯的最后几帧:
以下是Python中典型Nevow回溯的最后几帧:
不仅仅是网络环境,你可以在ipython和irb之间进行类似的比较。如何在Ruby中获得更多这类细节?
答案 0 :(得分:7)
AFAIK,一旦发现异常,就抓住它被引发的背景为时已晚。如果你捕获异常的新调用,你可以使用evil.rb的Binding.of_caller来获取调用范围,然后执行
eval("local_variables.collect { |l| [l, eval(l)] }", Binding.of_caller)
但这是一个非常大的黑客。正确的答案可能是扩展Ruby以允许对调用堆栈进行一些检查。我不确定是否有一些新的Ruby实现允许这样做,但我确实记得对Binding.of_caller的强烈反对,因为它会使优化变得更加困难。
(说实话,我不理解这种反对意见:只要解释器记录了有关所执行优化的足够信息,Binding.of_caller应该能够工作,尽管可能很慢。)
好的,我明白了。 Longish代码如下:
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