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
嘿,圖像鏈接已損壞。 – alanjds 2017-11-01 16:17:26