Ruby抢救块

cotxawn7  于 2023-06-22  发布在  Ruby
关注(0)|答案(2)|浏览(74)

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

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

不幸的是,上面的脚本不起作用。仅运行第一个命令。
我想强制rescue块运行多行代码,如下所示:

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,根据我的导师的说法,这是不正确的。

eh57zj3b

eh57zj3b1#

使用&&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
5w9g7ksd

5w9g7ksd2#

有一个retry内置。这个例子来自“Ruby编程语言”第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

相关问题