Ruby on rails ruby:在发生异常后在同一循环迭代中继续
我觉得有点奇怪,因为有很多问题有点像这样,但距离不够近,或者没有答案 [编辑:我正在重新表述问题,以使其更清楚] 我有一个循环,它可以做很多事情,我在玩它,看看各种选项是否可以使事情更可读、更清晰。最后,我搞砸了一些东西,它抛出了一个异常,这被救援人员抓住了。到现在为止,一直都还不错。然而,我找不到任何方法让ruby在循环的同一个迭代中继续执行以下语句——异常总是导致以下语句,并继续执行下一个迭代——默认行为。重做或重试将毫无意义,并导致无限循环,再次遇到相同的错误和异常,等等 我想知道有没有办法强迫ruby以某种方式处理错误,然后继续它停止的地方 这是一个样本,从我不知道的地方偷来的Ruby on rails ruby:在发生异常后在同一循环迭代中继续,ruby-on-rails,ruby,Ruby On Rails,Ruby,我觉得有点奇怪,因为有很多问题有点像这样,但距离不够近,或者没有答案 [编辑:我正在重新表述问题,以使其更清楚] 我有一个循环,它可以做很多事情,我在玩它,看看各种选项是否可以使事情更可读、更清晰。最后,我搞砸了一些东西,它抛出了一个异常,这被救援人员抓住了。到现在为止,一直都还不错。然而,我找不到任何方法让ruby在循环的同一个迭代中继续执行以下语句——异常总是导致以下语句,并继续执行下一个迭代——默认行为。重做或重试将毫无意义,并导致无限循环,再次遇到相同的错误和异常,等等 我想知道有没有办
3.times do |i|
begin
# first bunch of stuff to do
# second bunch of stuff to do
# third bunch of stuff to do
# fourth bunch of stuff to do
rescue => e
p e
end
end
基本上,在本例中,我希望在继续循环的下一次迭代之前执行所有四组内容,即使其中一个会导致错误。我没有处理错误,允许我看到异常结果,等等,但实际上忽略了它,继续做所有其他的事情
有什么想法吗?这可能是我以前从未见过的非常明显的东西。一个
开始
块(包括saydef
中的隐式块)在第一个异常处结束。如果你想在做完某件事后,不管成败,都要分开做,那么就把它放在块外
3.times do |i|
begin
raise "Raised from iteration #{i}"
rescue => e
p e
end
puts "I'm after the exception"
end
如果您想在返回
、中断
等之后执行某项操作,请使用确保
块
5.times do |i|
begin
break if i == 3
raise "Raised from iteration #{i}"
rescue => e
p e
ensure
puts "I always run #{i}"
end
end
哪些产出:
#<RuntimeError: Raised from iteration 0>
I always run 0
#<RuntimeError: Raised from iteration 1>
I always run 1
#<RuntimeError: Raised from iteration 2>
I always run 2
I always run 3
产出:
Supressing I throw sometimes 0
After possible exceptions 0
Supressing I throw sometimes 1
After possible exceptions 1
Supressing I throw sometimes 2
After possible exceptions 2
Supressing I throw sometimes 3
Supressing I throw sometimes too 3
After possible exceptions 3
Supressing I throw sometimes too 4
After possible exceptions 4
您正在使用
rescue
子句定义begin-end
块。如果块引发任何异常,并且存在匹配的rescue子句,则块将停止执行,rescue子句将被执行。如果没有匹配的rescue块,错误将冒泡(希望由另一个块处理,否则将不处理,脚本将停止!)如果有sure
子句,即使出现异常,也会运行该子句
那我们该怎么办?如果您想防御单个步骤的失败并继续执行,则每个步骤都需要自己的块:
3.times do |i|
begin
first_thing
rescue => e
puts "The first thing blew up! #{e.inspect}"
puts "I'll carry on anyway ¯\\_(ツ)_/¯"
end
begin
second_thing
third_thing
rescue => e
puts "Either the second or third thing blew up... #{e.inspect}"
puts "Straight on to the fourth thing!"
end
begin
fourth_thing
rescue => e
puts "Fourth thing blew up! #{e.inspect}"
end
end
有这样一个块是有点不寻常的,如果出现问题,它应该继续执行——这通常也是使下一个步骤出错的好方法!您可能需要确保在每个点上仍然具有数据完整性,并且后面的步骤不依赖于在前面的步骤中可能失败的某些事情。是否应该执行
puts
,而不管是否发生异常?是。这模拟了我正在处理的主程序中的字符串操作等。如果你在流控制中使用故意的异常,那可能是错误的。为什么不只是一个if
?顺便说一句,谢谢您的编辑-您编辑它时,我刚刚添加了“”“我有一个循环可以做很多事情”——也许你应该提供一个更详细的例子。很难根据循环中的单个开始救援块给出建议:-)感谢Fire Lancer-但如果您知道某段代码可能会通过并出现异常,那么这是可行的。如果您不知道,或者不知道是哪一部分,那么您希望援救工作能够围绕所有代码展开,因此您不必这样做。想象一下,加薪实际上是一堆东西,在某些情况下,可能会抛出异常。一般来说,在异常之后继续“下一个语句”是不安全的,而且会很困难,如果你真的想,你需要以某种方式显式地包装它们,或者分开显式开始块,或者是一些包装方法,你不想写推过异常并继续运行的YOLO代码。注意,由于这是用ruby on rails标记的,所以ActiveSupport为你添加了一个方法,假设你没有从itThanks all得到put
语句,那么我想我有我的答案了。实际上,没有什么内置的方法来处理错误,然后继续。如果我想这样做,分开的街区是最好的选择。这有点笨重,但你很少能得到生活中的一切!这里的基础是从一个文件中读取一行,在检查网络是否正常后,文件是否存在并可以打开,我们实际上得到了一行,然后对它/用它做了大量独立的事情,因此我对它感到满意,直到出现这种错误和情况,这让我在花了一天时间在非工作解决方案上之后走上了这条道路
3.times do |i|
begin
first_thing
rescue => e
puts "The first thing blew up! #{e.inspect}"
puts "I'll carry on anyway ¯\\_(ツ)_/¯"
end
begin
second_thing
third_thing
rescue => e
puts "Either the second or third thing blew up... #{e.inspect}"
puts "Straight on to the fourth thing!"
end
begin
fourth_thing
rescue => e
puts "Fourth thing blew up! #{e.inspect}"
end
end