如何在ruby traceback中获取源和变量值? [英] How can I get source and variable values in ruby tracebacks?

查看:117
本文介绍了如何在ruby traceback中获取源和变量值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是典型的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆