【问题标题】:Create full Exception object in Ruby在 Ruby 中创建完整的异常对象
【发布时间】:2014-02-27 21:23:21
【问题描述】:

我想要一个 Exception 对象的引用,其中包含所有正常信息 - 消息、回溯等。

异常有一个new 方法,但它不填充回溯:

exception = Exception.new("my message")
exception.backtrace
#=> nil

文档说有一个set_backtrace 方法,但您必须自己提供回溯(它不只是使用当前堆栈)。

我可以通过提升和救援来解决这个问题:

exception = begin
  raise Exception, "my message"
rescue Exception => e
  e
end
exception.backtrace
#=> ["(irb):4:in 'irb_binding'", ...]

但感觉不是很干净。

有没有一种简单的方法来创建一个完全填充的 Exception 对象?

【问题讨论】:

    标签: ruby exception


    【解决方案1】:

    当前堆栈跟踪可以从Kernel#caller获取,所以你可以这样做

    exception = Exception.new("my message")
    exception.set_backtrace(caller)
    

    我猜想创建一个Exception 对象而不立即提升它基本上只有在您计划传递它时才有意义。因此,必须手动设置回溯是有意义的。

    【讨论】:

    • 这就是我要找的。谢谢你。让它成为一个班轮会很好,但我认为你是对的 - 这样确实更有意义。
    【解决方案2】:

    相信你想要的是Kernel#caller_locations:

    def a; b; end
    def b; c; end
    
    def c
      caller_locations
    end
    
    a.each { |trace| p trace }
    # => 
    # "test.rb:2:in `b'"
    # "test.rb:1:in `a'"
    # "test.rb:8:in `<main>'"
    

    Kernel#caller 的区别在于调用者传递字符串对象。 caller_locations 提供 Thread::Backtrace::Location 对象。我没有看到任何其他差异,所以caller_locations 对我来说似乎更通用——拥有linenopath 等可能派上用场的方法。

    【讨论】:

    • 请注意caller_locations 包含Thread::Backtrace::Location 类型的对象,而caller 只返回Strings 的数组。除此之外,它们包含相同的位置。
    • @p11y 嘿,我只是在看那个并更新了我的答案,而没有注意到您的回复。但是,是的,你当然是对的 :)
    • 顺便说一句,这不是批评,只是注意到了 :) caller_locations 实际上在大多数情况下会派上用场!
    • 我知道,您指出它是对的,这是很好的补充信息!
    • 一些很好的信息,但不幸的是set_backtrace 不能接受Thread::Backtrace::Location 对象的数组。它必须是一个字符串数组。
    猜你喜欢
    • 2021-07-13
    • 2018-04-02
    • 2022-07-22
    • 2015-03-20
    • 1970-01-01
    • 2011-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多