在 Ruby 中,是否有在救援期间出现异常时创建的可用绑定?

In Ruby, is there a Binding available that is created at the time of the exception available during the rescue?

提问人:pedz 提问时间:3/22/2022 更新时间:3/23/2022 访问量:66

问:

我遇到的确切痛点是我正在解析文件列表。每个文件都有多行。当出现问题时,我想打印出诸如当前文件名、当前行号、当前行和其他一些有趣的变量之类的内容,然后在大多数情况下退出,因为错误将出现在我的代码中,需要增强。

大多数变量是嵌套块的局部变量。有很多地方可能会出错。#each

我想做的是只有一个全局 , , 块,并在 中有一个可供我使用的变量,这样我就可以挖掘出我有兴趣打印出来的各种变量。beginrescueendrescueBinding

这似乎是一个相当明显的事情,所以我觉得很奇怪,我是第一个想要这样东西的人。然而,我在 Ruby 文档的异常处理部分没有看到任何闭包概念。通常这意味着我从根本上滥用了语言的概念。RubyBinding

Ruby 异常 绑定 救援

评论

0赞 Todd A. Jacobs 3/26/2022
请在您的问题中添加一些代码。虽然您可以随时调用 Binding#new,但深度嵌套的循环通常是一种代码气味,因此这似乎是一个潜在的 X/Y 问题。如果在异常处理程序的右向分配中没有所需的内容,则可能会造成不必要的复杂性,而不是以可测试的方式使用正确的对象和方法。

答:

0赞 Leon 3/23/2022 #1

好吧,最简单的方法是在 .begin ... rescue ... end block

然后,您可以在救援块中轻松访问它们:

variable = 0
another_variable = 0
begin
    3.times do |a|
        variable = a
        5.times do |b|
            another_variable = b
            if a == 2 and b == 4
                raise KeyError
            end
        end
    end
    at_exit do
        puts binding.eval 'variable'
        puts binding.eval 'another_variable'
    end
rescue KeyError
    puts variable
    puts another_variable
end

但是,如果您想在异常发生之前获得最后一个 - 您的解决方案是使用 TracePoint: https://ruby-doc.org/core-2.5.0/TracePoint.htmlbinding

这允许您跟踪定义了所需局部变量的绑定,然后获取最后一个绑定。当然,如果你使用这种方法,它会让你的程序变慢一点。使用示例:

last_binding = nil
trace = TracePoint.new(:b_return) do |tp|
  last_binding = tp.binding if tp.binding.local_variable_defined?('variable')
end

trace.enable

begin
    3.times do |a|
        variable = a
        5.times do |b|
            another_variable = b
            if a == 2 and b == 4
                raise KeyError
            end
        end
    end
    at_exit do
        puts binding.eval 'variable'
        puts binding.eval 'another_variable'
    end
rescue KeyError
    trace.disable
    puts last_binding.eval 'another_variable'
end

(最适合您跟踪的事件是 - 它发生在每个区块结束之后,因此这将使您的跟踪时间达到最佳状态)b_return

评论

0赞 pedz 3/23/2022
谢谢。我知道我可以使用全局变量......这对我来说简直太恶心了。Tracepoint 听起来像是一个跟踪工具。异常的运行时开销为零,但跟踪为零。追踪还有其他微妙的、难以诊断的副作用。听起来我问题的真正答案是“不”。我想我会在 Ruby bug 网站上提交一个功能。