【问题标题】:ruby rescue block -- respond with more than just one commandruby 救援块——响应不止一个命令
【发布时间】:2014-03-06 03:02:10
【问题描述】:

我正在使用经常超时的 API 运行脚本。发生这种情况时,我使用begin/rescue 块将其发送到redo,但我想在运行redo 命令之前将发生的情况记录到命令行。

begin
#...api query...
rescue ErrorClass
  puts("retrying #{id}") && redo
end

不幸的是,上面的脚本不起作用。只运行第一个命令。

我想强制救援块运行多行代码,如下所示:

begin
 # api query
rescue ErrorClass do ###or:# rescue ErrorClass do |e|
  puts "retrying #{id}"
  redo
 end

但那些也不起作用。

我很幸运地创建了一个单独的方法来像这样运行:

def example
  id = 34314
  begin
    5/0
  rescue ZeroDivisionError
    eval(handle_zerodiv_error(id))
  end
end

def handle_zerodiv_error(id)
  puts "retrying #{id}"
  "redo"
end

...确实有效。但在我看来,它需要太多的代码行,而且它使用了 eval,根据我的导师的说法,这无论如何都不是 kosher。

【问题讨论】:

  • 你的代码中redo 的目的是什么,我没有得到你要找的东西
  • 大多数情况下,我能够以发生错误的给定 id 重新开始该过程并且它可以工作。因此,我试图在没有脚本中断的情况下做到这一点。在某些情况下,不可避免地会导致错误的 API 命令本身,所以我想知道脚本何时卡在同一个 id 上。
  • 我想强制救援块运行多行代码 - 有什么问题?你的意思是最后一行没有执行?

标签: ruby eval next rescue redo


【解决方案1】:

使用&&do 会使事情变得不必要地复杂化。 && 版本不起作用,因为puts 返回nil,因此通过&& 的快捷评估,不评估后续部分。如果您改用||;,那么它将起作用:

begin
  ...
rescue ErrorClass
  puts("retrying #{id}") || redo
end

begin
  ...
rescue ErrorClass
  puts("retrying #{id}"); redo
end

但即使这样也没有必要。您似乎认为您需要在rescue 中使用一个块来编写多行,但这没有意义,因为您没有使用单行块。没有 Ruby 构造仅在您有多行时才需要块。所以,只需将它们放在多行中:

begin
  ...
rescue ErrorClass
  puts("retrying #{id}")
  redo
end

【讨论】:

    【解决方案2】:

    有一个内置的retry。这个例子来自“The Ruby Programming Language”第162页。

    require  "open-uri"
    
    tries = 0
    begin
      tries +=1
      open("http://www.example.com/"){|f| puts f.readlines}
    rescue OpenURI::HTTPError => e
      puts e.message
      if (tries < 4)
        sleep (2**tries)  # wait for 2, 4 or 8 seconds
        retry             # and try again
      end
    end
    

    【讨论】:

    • 我认为retry 会再次尝试整个Enumerable 组(array),redo 只会再次尝试给定的Enumberable 成员(array[n]
    猜你喜欢
    • 2012-02-26
    • 2023-01-13
    • 1970-01-01
    • 2013-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多