Ruby - 异常处理

Ruby - 异常处理 首页 / Ruby入门教程 / Ruby - 异常处理

如果程序发生异常,程序将停止执行。因此异常(Exceptions)用于处理各种类型的错误,这些错误可能在程序执行期间发生,并采取适当的措施而不是完全停止程序运行。

Ruby提供了一种很好的机制来处理异常,无涯教程将可能引发异常的代码封装在 begin/end 块中,并使用 rescue 子句处理的异常类型。

异常语法

begin  
# -  
rescue OneTypeOfException  
# -  
rescue AnotherTypeOfException  
# -  
else  
# Other exceptions
ensure
# Always will be executed
end

在执行此代码块期间发生异常,则将控制权传递给 rescueend 之间的块。

对于 begin 块中的每个 rescue 子句,Ruby依次将引发的异常与每个参数进行比较。如果与当前抛出的异常的类型相同,或者是该异常的超类,则匹配将成功。

如果异常与指定的任何错误类型都不匹配,则允许在所有 rescue 子句之后使用 else 子句。

#!/usr/bin/ruby

begin
   file=open("/unexistant_file")
   if file
      puts "File opened successfully"
   end
rescue
      file=STDIN
end
print file, "==", STDIN, "\n"

这将产生以下输出。您会看到 STDIN 被替换为文件,因为打开失败。

#<IO:0xb7d16f84>==#<IO:0xb7d16f84>

Rescue 语句

您可以使用 rescue 块捕获异常,然后使用 retry 语句从头开始执行 begin 块。

begin
   # Exceptions raised by this code will 
   # be caught by the following rescue clause
rescue
   # This block will capture all types of exceptions
   retry  # This will move control to the beginning of begin
end

示例

#!/usr/bin/ruby

begin
   file=open("/unexistant_file")
   if file
      puts "File opened successfully"
   end
rescue
   fname="existant_file"
   retry
end

Retry 语句

您可以使用 raise 语句引发异常。每当调用以下方法时,都会引发异常。这是第二条消息将被打印。

raise 

OR

raise "Error Message" 

OR

raise ExceptionType, "Error Message"

OR

raise ExceptionType, "Error Message" condition

第一种形式只是重新引发当前异常(如果没有当前异常,则引发RuntimeError) ,这用于需要在传递异常之前拦截异常的异常处理程序。

第二种形式创建一个新的 RuntimeError 异常,将其消息设置为给定的字符串,然后在调用堆栈中引发此异常。

第三种形式使用第一个参数创建异常,然后将关联的消息设置为第二个参数。

第四种形式类似于第三种形式,但是您可以添加任何条件语句,如除非引发异常。

#!/usr/bin/ruby

begin  
   puts 'I am before the raise.'  
   raise 'An error has occurred.'  
   puts 'I am after the raise.'  
rescue  
   puts 'I am rescued.'  
end  
puts 'I am after the begin block.'  

这将产生以下输出-

I am before the raise.  
I am rescued.  
I am after the begin block.  

另一个示例显示 raise 的用法-

#!/usr/bin/ruby

begin  
   raise 'A test exception.'  
rescue Exception => e  
   puts e.message  
   puts e.backtrace.inspect  
end  

这将产生以下输出-

A test exception.
["main.rb:4"]

Raise 语句

有时,您需要保证在代码块的末尾进行某些处理,而不管是否引发异常。如您可能在该块的入口处打开了一个文件,并且需要确保在该块退出时该文件已关闭。

begin 
   #.. process 
   #..raise exception
rescue 
   #.. handle error 
ensure 
   #.. finally ensure execution
   #.. This will always execute.
end

示例

begin
   raise 'A test exception.'
rescue Exception => e
   puts e.message
   puts e.backtrace.inspect
ensure
   puts "Ensuring execution"
end

这将产生以下输出-

A test exception.
["main.rb:4"]
Ensuring execution

else 语句

如果存在 else 子句,则该子句将在 rescue 子句之后并在任何 ensure 之前。

else 子句的主体仅在代码主体未引发任何异常的情况下才执行。

begin 
   #.. process 
   #..raise exception
rescue 
   # .. handle error
else
   #.. executes if there is no exception
ensure 
   #.. finally ensure execution
   #.. This will always execute.
end

示例

begin
   # raise 'A test exception.'
   puts "I'm not raising exception"
rescue Exception => e
   puts e.message
   puts e.backtrace.inspect
else
   puts "Congratulations-- no errors!"
ensure
   puts "Ensuring execution"
end

这将产生以下输出-

I'm not raising exception
Congratulations-- no errors!
Ensuring execution

Catch & Throw 语句

catch 定义一个标有给定名称(可以是符号或字符串)的块。该块将正常执行,直到遇到抛出。

throw :lablename
#.. this will not be executed
catch :lablename do
#.. matching catch will be executed after a throw is encountered.
end

OR

throw :lablename condition
#.. this will not be executed
catch :lablename do
#.. matching catch will be executed after a throw is encountered.
end

下面的示例使用抛出来终止与用户的交互(如果为"!")。根据任何提示输入。

def promptAndGet(prompt)
   print prompt
   res=readline.chomp
   throw :quitRequested if res == "!"
   return res
end

catch :quitRequested do
   name=promptAndGet("Name: ")
   age=promptAndGet("Age: ")
   sex=promptAndGet("Sex: ")
   # ..
   # process information
end
promptAndGet("Name:")

这将产生以下输出-

Name: Ruby on Rails
Age: 3
Sex: !
Name:Just Ruby

类异常

Ruby的标准类和模块会引发异常。所有异常类都构成一个层次结构,顶部是Exception类。下一级别包含七种不同的类型-

  • Interrupt
  • NoMemoryError
  • SignalException
  • ScriptError
  • StandardError
  • SystemExit

在这个级别上还有一个ExceptionFatal ,但是Ruby解释器仅在内部使用此Exception

ScriptErrorStandardError都有许多子类,但是不需要在这里详细介绍。如果创建自己的异常类,则它们必须是Exception类或其子类之一。

让无涯教程看一个示例-

class FileSaveError < StandardError
   attr_reader :reason
   def initialize(reason)
      @reason=reason
   end
end

现在,看下面的示例,它将使用此异常-

File.open(path, "w") do |file|
begin
   # Write out the data ...
rescue
   # Something went wrong!
   raise FileSaveError.new($!)
end
end

祝学习愉快!(内容编辑有误?请选中要编辑内容 -> 右键 -> 修改 -> 提交!)

技术教程推荐

程序员的数学基础课 -〔黄申〕

Web协议详解与抓包实战 -〔陶辉〕

全栈工程师修炼指南 -〔熊燚(四火)〕

深入浅出云计算 -〔何恺铎〕

To B市场品牌实战课 -〔曹林〕

全链路压测实战30讲 -〔高楼〕

反爬虫兵法演绎20讲 -〔DS Hunter〕

云计算的必修小课 -〔吕蕴偲〕

B端产品经理入门课 -〔董小圣〕

好记忆不如烂笔头。留下您的足迹吧 :)