begin # Some code which may cause an exception rescue <Exception Class> # Code to recover from the exception end
AI 代码解读
例如 :
begin x = 1/0 rescue Exception x = 0 puts( $!.class ) puts( $! ) end puts( x )
AI 代码解读
执行结果 :
ZeroDivisionError divided by 0 0
AI 代码解读
class ZeroDivisionError def to_s return "you cann't divided by 0" end end begin x = 1/0 rescue Exception x = 0 puts( $!.class ) puts( $! ) end puts( x )
AI 代码解读
执行结果 :
ZeroDivisionError you cann't divided by 0 0
AI 代码解读
def calc( val1, val2 ) return val1 / val2 end begin result = calc(10,0) rescue Exception => e1 puts(e1.class) puts(e1) result = 0 end puts(result)
AI 代码解读
执行结果 :
ZeroDivisionError divided by 0 0
AI 代码解读
接下来我们来看看Exception的继承关系 :
def putclass(obj1) p(obj1.superclass) if obj1.superclass != nil then putclass(obj1.superclass) end end putclass(ZeroDivisionError)
AI 代码解读
输出结果 :
StandardError Exception Object BasicObject nil
AI 代码解读
def putclass(obj1) p(obj1.superclass) if obj1.superclass != nil then putclass(obj1.superclass) end end def calc( val1, val2 ) return val1 / val2 end begin result = calc("a",0) rescue Exception => e1 puts(e1.class) puts(e1) result = 0 end puts(result) putclass(e1.class) begin result = calc(10,"a") rescue Exception => e1 puts(e1.class) puts(e1) result = 0 end puts(result) putclass(e1.class)
AI 代码解读
输出结果 :
NoMethodError undefined method `/' for "a":String 0 NameError StandardError Exception Object BasicObject nil TypeError String can't be coerced into Fixnum 0 StandardError Exception Object BasicObject nil
AI 代码解读
def calc( val1, val2 ) begin result = val1 / val2 rescue TypeError, NoMethodError => e puts( e.class ) puts( e ) puts( "One of the values is not a number!" ) result = nil rescue Exception => e puts( e.class ) puts( e ) result = nil end return result end p calc("a",1)
AI 代码解读
执行结果 :
NoMethodError undefined method `/' for "a":String One of the values is not a number! nil
AI 代码解读
startdir = Dir.getwd begin Dir.chdir( "X:\\" ) # 假设这个目录不存在或为空 puts( `dir` ) rescue Exception => e puts e.class puts e ensure Dir.chdir( startdir ) end p startdir p Dir.getwd
AI 代码解读
执行结果 :
Errno::ENOENT No such file or directory - X:\ "C:/Users/digoal/Desktop" "C:/Users/digoal/Desktop
"AI 代码解读
再来测试一个,
# cat test.rb #!/opt/ruby/bin/ruby f = File.new( "text" ) begin for i in (1..6) do puts("line number: #{f.lineno}") line = f.gets.chomp num = line.to_i puts( "Line '#{line}' is converted to #{num}" ) puts( 100 / num ) end rescue Exception => e puts( e.class ) puts( e ) ensure f.close puts( "File closed" ) end # text文件的最后一行是字符串, 无法转换为Fixnum, 因此会捕获到异常, # 不管有没有异常我们都需要关闭这个文件. 因此ensure代码中写了f.close # cat text 1 2 3 4 5 jd
AI 代码解读
执行结果 :
line number: 0 Line '1' is converted to 1 100 line number: 1 Line '2' is converted to 2 50 line number: 2 Line '3' is converted to 3 33 line number: 3 Line '4' is converted to 4 25 line number: 4 Line '5' is converted to 5 20 line number: 5 Line 'jd' is converted to 0 ZeroDivisionError divided by 0 File closed
AI 代码解读
begin # code which may cause an exception rescue [Exception Type] else # optional section executes if no exception occurs ensure # optional exception always executes end
AI 代码解读
例如 :
def doCalc( aNum ) begin result = 100 / aNum.to_i rescue Exception => e # executes when there is an error result = 0 msg = "Error: " + e.to_s else # executes when there is no error msg = "Result = #{result}" ensure # always executes msg = "You entered '#{aNum}'. " + msg end return msg end p doCalc("a") p doCalc(1)
AI 代码解读
执行结果 :
"You entered 'a'. Error: divided by 0" "You entered '1'. Result = 100"
AI 代码解读
def showFamily( aClass ) if (aClass != nil) then puts( "#{aClass} :: about to recurse with aClass.superclass = #{aClass.superclass.inspect}" ) showFamily( aClass.superclass ) end end def chDisk( aChar ) startdir = Dir.getwd begin Dir.chdir( "#{aChar}:\\" ) puts( `dir` ) rescue Exception => e showFamily( e.class ) # to see ancestors, uncomment puts e.class # ...and comment out this puts e ensure Dir.chdir( startdir ) end end chDisk( "F" ) # F是我的光驱, 没放光盘, chDisk( "X" ) # X是一个不存在的盘, chDisk( "ABC" ) # ABC则是一个格式错误的盘符.
AI 代码解读
执行结果 :
Errno::EACCES :: about to recurse with aClass.superclass = SystemCallError SystemCallError :: about to recurse with aClass.superclass = StandardError StandardError :: about to recurse with aClass.superclass = Exception Exception :: about to recurse with aClass.superclass = Object Object :: about to recurse with aClass.superclass = BasicObject BasicObject :: about to recurse with aClass.superclass = nil Errno::EACCES Permission denied - F:\ Errno::ENOENT :: about to recurse with aClass.superclass = SystemCallError SystemCallError :: about to recurse with aClass.superclass = StandardError StandardError :: about to recurse with aClass.superclass = Exception Exception :: about to recurse with aClass.superclass = Object Object :: about to recurse with aClass.superclass = BasicObject BasicObject :: about to recurse with aClass.superclass = nil Errno::ENOENT No such file or directory - X:\ Errno::EINVAL :: about to recurse with aClass.superclass = SystemCallError SystemCallError :: about to recurse with aClass.superclass = StandardError StandardError :: about to recurse with aClass.superclass = Exception Exception :: about to recurse with aClass.superclass = Object Object :: about to recurse with aClass.superclass = BasicObject BasicObject :: about to recurse with aClass.superclass = nil Errno::EINVAL Invalid argument - ABC:\
AI 代码解读
Ruby exception objects are subclasses of Exception. However, operating systems typically report errors using plain integers. Module Errno is created dynamically to map these operating system errors to Ruby classes, with each error number generating its own subclass of SystemCallError. As the subclass is created in module Errno, its name will start Errno::.
The names of the Errno:: classes depend on the environment in which Ruby runs. On a typical Unix or Windows platform, there are Errno classes such as Errno::EACCES, Errno::EAGAIN, Errno::EINTR, and so on.
The integer operating system error number corresponding to a particular error is available as the class constantErrno::error::Errno.
Errno::EACCES::Errno #=> 13 Errno::EAGAIN::Errno #=> 11 Errno::EINTR::Errno #=> 4
The full list of operating system errors on your particular platform are available as the constants of Errno.
Errno.constants #=> :E2BIG, :EACCES, :EADDRINUSE, :EADDRNOTAVAIL, ...
p Errno.constants.sort [:E2BIG, :EACCES, :EADDRINUSE, :EADDRNOTAVAIL, :EADV, :EAFNOSUPPORT, :EAGAIN, :EALREADY, :EAUTH, :EBADE, :EBADF, :EBADFD, :EBADMSG, :EBADR, :EBADRPC, :EBADRQC, :EBADSLT, :EBFONT, :EBUSY, :ECANCELED, :ECHILD, :ECHRNG, :ECOMM, :ECONNABORTED, :ECONNREFUSED, :ECONNRESET, :EDEADLK, :EDEADLOCK, :EDESTADDRREQ, :EDOM, :EDOOFUS, :EDOTDOT, :EDQUOT, :EEXIST, :EFAULT, :EFBIG, :EFTYPE, :EHOSTDOWN, :EHOSTUNREACH, :EIDRM, :EILSEQ, :EINPROGRESS, :EINTR, :EINVAL, :EIO, :EIPSEC, :EISCONN, :EISDIR, :EISNAM, :EKEYEXPIRED, :EKEYREJECTED, :EKEYREVOKED, :EL2HLT, :EL2NSYNC, :EL3HLT, :EL3RST, :ELIBACC, :ELIBBAD, :ELIBEXEC, :ELIBMAX, :ELIBSCN, :ELNRNG, :ELOOP, :EMEDIUMTYPE, :EMFILE, :EMLINK, :EMSGSIZE, :EMULTIHOP, :ENAMETOOLONG, :ENAVAIL, :ENEEDAUTH, :ENETDOWN, :ENETRESET, :ENETUNREACH, :ENFILE, :ENOANO, :ENOATTR, :ENOBUFS, :ENOCSI, :ENODATA, :ENODEV, :ENOENT, :ENOEXEC, :ENOKEY, :ENOLCK, :ENOLINK, :ENOMEDIUM, :ENOMEM, :ENOMSG, :ENONET, :ENOPKG, :ENOPROTOOPT, :ENOSPC, :ENOSR, :ENOSTR, :ENOSYS, :ENOTBLK, :ENOTCONN, :ENOTDIR, :ENOTEMPTY, :ENOTNAM, :ENOTRECOVERABLE, :ENOTSOCK, :ENOTSUP, :ENOTTY, :ENOTUNIQ, :ENXIO, :EOPNOTSUPP, :EOVERFLOW, :EOWNERDEAD, :EPERM, :EPFNOSUPPORT, :EPIPE, :EPROCLIM, :EPROCUNAVAIL, :EPROGMISMATCH, :EPROGUNAVAIL, :EPROTO, :EPROTONOSUPPORT, :EPROTOTYPE, :ERANGE, :EREMCHG, :EREMOTE, :EREMOTEIO, :ERESTART, :ERFKILL, :EROFS, :ERPCMISMATCH, :ESHUTDOWN, :ESOCKTNOSUPPORT, :ESPIPE, :ESRCH, :ESRMNT, :ESTALE, :ESTRPIPE, :ETIME, :ETIMEDOUT, :ETOOMANYREFS, :ETXTBSY, :EUCLEAN, :EUNATCH, :EUSERS, :EWOULDBLOCK, :EXDEV, :EXFULL, :NOERROR]
AI 代码解读
查询Errno常量值 :
for err in Errno.constants.sort do errnum = eval( "Errno::#{err}::Errno" ) print( "#{err} #{errnum} ," ) end 结果 E2BIG 7 ,EACCES 13 ,EADDRINUSE 10048 ,EADDRNOTAVAIL 10049 ,EADV 0 ,EAFNOSUPPORT 10047 ,EAGAIN 11 ,EALREADY 10037 ,EAUTH 0 ,EBADE 0 ,EBADF 9 ,EBADFD 0 ,EBADMSG 0 ,EBADR 0 ,EBADRPC 0 ,EBADRQC 0 ,EBADSLT 0 ,EBFONT 0 ,EBUSY 16 ,ECANCELED 0 ,ECHILD 10 ,ECHRNG 0 ,ECOMM 0 ,ECONNABORTED 10053 ,ECONNREFUSED 10061 ,ECONNRESET 10054 ,EDEADLK 36 ,EDEADLOCK 36 ,EDESTADDRREQ 10039 ,EDOM 33 ,EDOOFUS 0 ,EDOTDOT 0 ,EDQUOT 10069 ,EEXIST 17 ,EFAULT 14 ,EFBIG 27 ,EFTYPE 0 ,EHOSTDOWN 10064 ,EHOSTUNREACH 10065 ,EIDRM 0 ,EILSEQ 42 ,EINPROGRESS 10036 ,EINTR 4 ,EINVAL 22 ,EIO 5 ,EIPSEC 0 ,EISCONN 10056 ,EISDIR 21 ,EISNAM 0 ,EKEYEXPIRED 0 ,EKEYREJECTED 0 ,EKEYREVOKED 0 ,EL2HLT 0 ,EL2NSYNC 0 ,EL3HLT 0 ,EL3RST 0 ,ELIBACC 0 ,ELIBBAD 0 ,ELIBEXEC 0 ,ELIBMAX 0 ,ELIBSCN 0 ,ELNRNG 0 ,ELOOP 10062 ,EMEDIUMTYPE 0 ,EMFILE 24 ,EMLINK 31 ,EMSGSIZE 10040 ,EMULTIHOP 0 ,ENAMETOOLONG 38 ,ENAVAIL 0 ,ENEEDAUTH 0 ,ENETDOWN 10050 ,ENETRESET 10052 ,ENETUNREACH 10051 ,ENFILE 23 ,ENOANO 0 ,ENOATTR 0 ,ENOBUFS 10055 ,ENOCSI 0 ,ENODATA 0 ,ENODEV 19 ,ENOENT 2 ,ENOEXEC 8 ,ENOKEY 0 ,ENOLCK 39 ,ENOLINK 0 ,ENOMEDIUM 0 ,ENOMEM 12 ,ENOMSG 0 ,ENONET 0 ,ENOPKG 0 ,ENOPROTOOPT 10042 ,ENOSPC 28 ,ENOSR 0 ,ENOSTR 0 ,ENOSYS 40 ,ENOTBLK 0 ,ENOTCONN 10057 ,ENOTDIR 20 ,ENOTEMPTY 41 ,ENOTNAM 0 ,ENOTRECOVERABLE 0 ,ENOTSOCK 10038 ,ENOTSUP 0 ,ENOTTY 25 ,ENOTUNIQ 0 ,ENXIO 6 ,EOPNOTSUPP 10045 ,EOVERFLOW 0 ,EOWNERDEAD 0 ,EPERM 1 ,EPFNOSUPPORT 10046 ,EPIPE 32 ,EPROCLIM 10067 ,EPROCUNAVAIL 0 ,EPROGMISMATCH 0 ,EPROGUNAVAIL 0 ,EPROTO 0 ,EPROTONOSUPPORT 10043 ,EPROTOTYPE 10041 ,ERANGE 34 ,EREMCHG 0 ,EREMOTE 10071 ,EREMOTEIO 0 ,ERESTART 0 ,ERFKILL 0 ,EROFS 30 ,ERPCMISMATCH 0 ,ESHUTDOWN 10058 ,ESOCKTNOSUPPORT 10044 ,ESPIPE 29 ,ESRCH 3 ,ESRMNT 0 ,ESTALE 10070 ,ESTRPIPE 0 ,ETIME 0 ,ETIMEDOUT 10060 ,ETOOMANYREFS 10059 ,ETXTBSY 0 ,EUCLEAN 0 ,EUNATCH 0 ,EUSERS 10068 ,EWOULDBLOCK 10035 ,EXDEV 18 ,EXFULL 0 ,NOERROR 0 ,
AI 代码解读
5. retry, Attempt to Execute code again after an error
#!/opt/ruby/bin/ruby def doCalc begin print( "Enter a number: " ) aNum = gets().chomp() result = 100 / aNum.to_i rescue Exception => e result = 0 puts( "Error: " + e.to_s + "\nPlease try again." ) # Ruby 1.9如果要在字符连接中使用Exception的返回值, 需要使用to_s方法. retry # retry on exception else msg = "Result = #{result}" ensure msg = "You entered '#{aNum}'. " + msg end return msg end doCalc
AI 代码解读
执行结果 :
./test.rb Enter a number: 0 Error: divided by 0 Please try again. Enter a number: "1" Error: divided by 0 Please try again. Enter a number: a Error: divided by 0 Please try again. Enter a number: 10
AI 代码解读
为了防止死循环, 可以加一个限制重试的次数.
#!/opt/ruby/bin/ruby def doCalc tries = 0 begin tries += 1 print( "Enter a number: " ) aNum = gets().chomp() result = 100 / aNum.to_i rescue Exception => e msg = "Error: " + e.to_s puts( msg ) puts( "tries = #{tries}" ) result = 0 if tries < 3 then # set a fixed number of retries retry end else msg = "Result = #{result}" ensure msg = "You entered '#{aNum}'. " + msg end return msg end doCalc
AI 代码解读
执行结果 :
./test.rb Enter a number: a Error: divided by 0 tries = 1 Enter a number: b Error: divided by 0 tries = 2 Enter a number: c Error: divided by 0 tries = 3
AI 代码解读
6. raise, Reactivate a Handled Error
With no arguments, raises the exception in $! or raises a RuntimeError if $! is nil. With a single Stringargument, raises a RuntimeError with the string as a message. Otherwise, the first parameter should be the name of an Exception class (or an object that returns an Exception object when sent an exception message). The optional second parameter sets the message associated with the exception, and the third parameter is an array of callback information. Exceptions are caught by the rescue clause of begin...end blocks.
raise "Failed to create socket" raise ArgumentError, "No parameters", caller
begin raise ZeroDivisionError.new( "I'm afraid you divided by Zero" ) rescue Exception => e puts( e.class ) puts( "message: " + e.to_s ) end
AI 代码解读
执行结果 :
ZeroDivisionError message: I'm afraid you divided by Zero
AI 代码解读
例子2 :
class NoNameError < Exception def to_str "No Name given!" end end def sayHello( aName ) begin if (aName == "") or (aName == nil) then raise NoNameError end rescue Exception => e puts( e.class ) puts( "error message: " + e.to_s ) puts( e.backtrace ) else puts( "Hello #{aName}" ) end end sayHello(nil)
AI 代码解读
执行结果 :
NoNameError error message: NoNameError C:/Users/digoal/Desktop/new.rb:9:in `sayHello' C:/Users/digoal/Desktop/new.rb:19:in `<main>'
AI 代码解读
Returns any backtrace associated with the exception. The backtrace is an array of strings, each containing either ``filename:lineNo: in `method’’’ or ``filename:lineNo.’‘
def a raise "boom" end def b a() end begin b() rescue => detail print detail.backtrace.join("\n") end
AI 代码解读
produces:
prog.rb:2:in `a' prog.rb:6:in `b' prog.rb:10
AI 代码解读
def calc result = 1/0 rescue Exception => e puts( e.class ) puts( e ) result = nil return result end class X @@x = 1/0 rescue Exception => e puts( e.class ) puts( e ) end module Y @@x = 1/0 rescue Exception => e puts( e.class ) puts( e ) end
AI 代码解读