【Ruby学习笔记】15.Ruby 异常
Ruby 异常
异常和执行总是被联系在一起。如果您打开一个不存在的文件,且没有恰当地处理这种情况,那么您的程序则被认为是低质量的。
如果异常发生,则程序停止。异常用于处理各种类型的错误,这些错误可能在程序执行期间发生,所以要采取适当的行动,而不至于让程序完全停止。
Ruby 提供了一个完美的处理异常的机制。我们可以在 begin/end 块中附上可能抛出异常的代码,并使用 rescue 子句告诉 Ruby 完美要处理的异常类型。
语法
begin #开始raise.. #抛出异常rescue [ExceptionType = StandardException] #捕获指定类型的异常默认值是 StandardException$! #表示异常信息$@ #表示异常出现的代码位置
else #其余异常..
ensure #不管有没有异常,进入该代码块end #结束
从 begin 到 rescue 中的一切是受保护的。如果代码块执行期间发生了异常,控制会传到 rescue 和 end 之间的块。
对于 begin 块中的每个 rescue 子句,Ruby 把抛出的异常与每个参数进行轮流比较。如果 rescue 子句中命名的异常与当前抛出的异常类型相同,或者是该异常的父类,则匹配成功。
如果异常不匹配所有指定的错误类型,我们可以在所有的 rescue 子句后使用一个 else 子句。
实例
#!/usr/bin/rubybeginfile = open("/unexistant_file")if fileputs "File opened successfully"end
rescuefile = STDIN
end
print file, "==", STDIN, "\n"
以上实例运行输出结果为。您可以看到,STDIN 取代了 file ,因为打开失败。
#<IO:0xb7d16f84>==#<IO:0xb7d16f84>
使用 retry 语句
您可以使用 rescue 块捕获异常,然后使用 retry 语句从开头开始执行 begin 块。
语法
begin# 这段代码抛出的异常将被下面的 rescue 子句捕获
rescue# 这个块将捕获所有类型的异常retry # 这将把控制移到 begin 的开头
end
实例
#!/usr/bin/rubybeginfile = open("/unexistant_file")if fileputs "File opened successfully"end
rescuefname = "existant_file"retry
end
以下是处理流程:
- 打开时发生异常。
- 跳到 rescue。fname 被重新赋值。
- 通过 retry 跳到 begin 的开头。
- 这次文件成功打开。
- 继续基本的过程。
注意:如果被重新命名的文件不存在,本实例代码会无限尝试。所以异常处理时,谨慎使用 retry。
使用 raise 语句
您可以使用 raise 语句抛出异常。下面的方法在调用时抛出异常。它的第二个消息将被输出。
语法
raise 或raise "Error Message" 或raise ExceptionType, "Error Message"或raise ExceptionType, "Error Message" condition
第一种形式简单地重新抛出当前异常(如果没有当前异常则抛出一个 RuntimeError)。这用在传入异常之前需要解释异常的异常处理程序中。
第二种形式创建一个新的 RuntimeError 异常,设置它的消息为给定的字符串。该异常之后抛出到调用堆栈。
第三种形式使用第一个参数创建一个异常,然后设置相关的消息为第二个参数。
第四种形式与第三种形式类似,您可以添加任何额外的条件语句(比如 unless)来抛出异常。
实例
#!/usr/bin/rubybegin 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/rubybegin raise 'A test exception.'
rescue Exception => e puts e.message puts e.backtrace.inspect
end
以上实例运行输出结果为:
A test exception.
["main.rb:4"]
使用 ensure 语句
有时候,无论是否抛出异常,您需要保证一些处理在代码块结束时完成。例如,您可能在进入时打开了一个文件,当您退出块时,您需要确保关闭文件。
ensure 子句做的就是这个。ensure 放在最后一个 rescue 子句后,并包含一个块终止时总是执行的代码块。它与块是否正常退出、是否抛出并处理异常、是否因一个未捕获的异常而终止,这些都没关系,ensure 块始终都会运行。
语法
begin #.. 过程#.. 抛出异常
rescue #.. 处理错误
ensure #.. 最后确保执行#.. 这总是会执行
end
实例
beginraise 'A test exception.'
rescue Exception => eputs e.messageputs e.backtrace.inspect
ensureputs "Ensuring execution"
end
以上实例运行输出结果为:
A test exception.
["main.rb:4"]
Ensuring execution
使用 else 语句
如果提供了 else 子句,它一般是放置在 rescue 子句之后,任意 ensure 之前。
else 子句的主体只有在代码主体没有抛出异常时执行。
语法
begin #.. 过程 #.. 抛出异常
rescue #.. 处理错误
else#.. 如果没有异常则执行
ensure #.. 最后确保执行#.. 这总是会执行
end
实例
begin# 抛出 'A test exception.'puts "I'm not raising exception"
rescue Exception => eputs e.messageputs e.backtrace.inspect
elseputs "Congratulations-- no errors!"
ensureputs "Ensuring execution"
end
以上实例运行输出结果为:
I'm not raising exception
Congratulations-- no errors!
Ensuring execution
使用 $! 变量可以捕获抛出的错误消息。
Catch 和 Throw
raise 和 rescue 的异常机制能在发生错误时放弃执行,有时候需要在正常处理时跳出一些深层嵌套的结构。此时 catch 和 throw 就派上用场了。
catch 定义了一个使用给定的名称(可以是 Symbol 或 String)作为标签的块。块会正常执行直到遇到一个 throw。
语法
throw :lablename
#.. 这不会被执行
catch :lablename do
#.. 在遇到一个 throw 后匹配将被执行的 catch
end或throw :lablename condition
#.. 这不会被执行
catch :lablename do
#.. 在遇到一个 throw 后匹配将被执行的 catch
end
实例
下面的实例中,如果用户键入 ‘!’ 回应任何提示,使用一个 throw 终止与用户的交互。
def promptAndGet(prompt)print promptres = readline.chompthrow :quitRequested if res == "!"return res
endcatch :quitRequested doname = promptAndGet("Name: ")age = promptAndGet("Age: ")sex = promptAndGet("Sex: ")# ..# 处理信息
end
promptAndGet("Name:")
上面的程序需要人工交互,您可以在您的计算机上进行尝试。以上实例运行输出结果为:
Name: Ruby on Rails
Age: 3
Sex: !
Name:Just Ruby
类 Exception
Ruby 的标准类和模块抛出异常。所有的异常类组成一个层次,包括顶部的 Exception 类在内。下一层是七种不同的类型:
- Interrupt
- NoMemoryError
- SignalException
- ScriptError
- StandardError
- SystemExit
Fatal 是该层中另一种异常,但是 Ruby 解释器只在内部使用它。
ScriptError 和 StandardError 都有一些子类,但是在这里我们不需要了解这些细节。最重要的事情是创建我们自己的异常类,它们必须是类 Exception 或其子代的子类。
让我们看一个实例:
实例
class FileSaveError < StandardErrorattr_reader :reasondef initialize(reason)@reason = reasonend
end
现在,看下面的实例,将用到上面的异常:
实例
File.open(path, "w") do |file|
begin# 写出数据 ...
rescue# 发生错误raise FileSaveError.new($!)
end
end
在这里,最重要的一行是 raise FileSaveError.new($!)。我们调用 raise 来示意异常已经发生,把它传给 FileSaveError 的一个新的实例,由于特定的异常引起数据写入失败。
相关文章:
【Ruby学习笔记】15.Ruby 异常
Ruby 异常 异常和执行总是被联系在一起。如果您打开一个不存在的文件,且没有恰当地处理这种情况,那么您的程序则被认为是低质量的。 如果异常发生,则程序停止。异常用于处理各种类型的错误,这些错误可能在程序执行期间发生&…...
聊聊MySQL主从延迟
文章目录 MySQL 的高可用是如何实现的呢?二、什么是主备延迟?三、主备延迟常见原因1、备库机器配置差2、备库干私活3、大事务四、主库不可用,主备切换有哪些策略?1、可靠优先2、可用优先实验一实验二3、结论MySQL 的高可用是如何实现的呢? 高可用性(high availability,缩…...
【C++从0到1】19、C++中多条件的if语句
C从0到1全系列教程 1、多条件的if语句 语法: if (表达式一) { // 表达式一为真时执行的语句。 } else if (表达式二) {// 表达式二为真时执行的语句。 } else if (表达式三) {// 表达式三为真时执行的语句。 } …… else if (表达式n) {// 表达式n为真时执行的语句。…...
【多微电网】计及碳排放的基于交替方向乘子法(ADMM)的多微网电能交互分布式运行策略研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
Linux(centos7)安装防火墙firewalld及开放端口相关命令
安装firewalld 防火墙命令: yum install firewalld 安装完成,查看防火墙状态为 not running,即未运行,输入命令开启: 添加开放端口: 防火墙相关命令: 查看防火墙状态 systemctl status firewa…...
Linux部署.Net Core Web项目
本文主要记录我在Linux(Ubuntu)上部署.net core 的操作记录,也便于以后部署。 如对您有所帮助,不胜荣幸~ 文章目录前言一、准备工作1. 版本信息2. windows端web项目二、操作步骤1. Linux 配置 .net 运行环境1.1 查看最新 .net 运行环境的下载路径1.2 安装…...
【C++】STL之stack、queue的使用和模拟实现+优先级队列(附仿函数)+容器适配器详解
之前的一段时间,我们共同学习了STL中一些容器,如string、vector和list等等。本章我们将步入新阶段的学习——容器适配器。本章将详解stack、queue的使用和模拟实现优先级队列(附仿函数)容器适配器等。 目录 (一&…...
第⑦讲:Ceph集群RGW对象存储核心概念及部署使用
文章目录1.RadosGW对象存储核心概念1.1.什么是RadosGW对象存储1.2.RGW对象存储架构1.3.RGW对象存储的特点1.4.对象存储中Bucket的特性1.4.不同接口类型的对象存储访问对比2.在集群中部署RadosGW对象存储组件2.1.部署RGW组件2.2.集群中部署完RGW组件后观察集群的信息状态2.3.修改…...
从异步到promise
一,背景 1.1,js的单线程 这一切,要从js诞生之初说起,因为js是单线程的语言。 js单线程原因:作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程&…...
Linux系统中进行JDK环境的部署
一、为什么需要部署JDK。 JDK:Java Development Kit,是用于Java语言开发的环境。 部署JDK不需要懂得Java语言,只需要掌握Linux相关命令即可。 二、部署版本与环境。 系统:安装在VMware环境下的CentOS7.6; JDK版本&a…...
Leetcode.1033 移动石子直到连续
题目链接 Leetcode.1033 移动石子直到连续 Rating : 1421 题目描述 三枚石子放置在数轴上,位置分别为 a,b,c。 每一回合,你可以从两端之一拿起一枚石子(位置最大或最小),并将其放入…...
【Java】在SpringBoot中使用事务注解(@Transactional)时需要注意的点
在SpringBoot中使用事务注解(Transactional)时需要注意的点Transactional是什么使用事务注解(Transactional)时需要注意的点Transactional是什么 Transactional是Spring框架提供的一个注解,用于声明事务边界和配置事务…...
找到序列最高位的1和最高位的0并输出位置
前言: 该题为睿思芯科笔试题,笔试时长20分钟。 题目描述 接口如下: module first_1_and_0#(parameter WIDTH 8 )(input [WIDTH-1:0] data_in ,input target ,output exist ,outpu…...
面试总结sdiugiho
一、进程与线程的区别 进程: 一个在内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程可以有多个线程; windows 任务管理器中 一个 exe 就是一个进程。 线程: 进程中的一个执行任务(控制…...
WIN10無法再使用 IE 瀏覽器打开网页解决办法
修改 Registry(只適用 Win10) 微軟已於 2023 年 2 月 14 日永久停用 Internet Explorer,會透過 Edge 的更新讓使用者開啟 IE 時自動導向 Edge,其餘如工作列上的圖示,使用的方法則是透過「品質更新」的 B 更新來達成&am…...
搭建SpringBoot和Mysql Demo
1. 引言 在上一篇文章中,介绍了如何搭建一个SpringBoot项目;本篇文章,在上一篇文章的基础上,接着介绍下怎样实现SpringBoot和MySQL的整合。在后端开发中,数据库开发是绕不开的话题,开发中很多的时间都是在…...
晶振03——晶振烧坏的原因
晶振03——晶振烧坏的原因 首先要清楚的一件事情是:晶振分为无源晶振与有源晶振两大类。基于这两类晶振的内部结构与工作原理的差异,晶振被烧坏的情况也要分为两大类: 针对无源晶振被烧坏的情况有以下两点: 1、手焊操作不当 假…...
项目管理的难点
一、项目团队建设 建设一支高效的项目团队,明确团队队员的职责是项目经理进行项目管理的首要条件,也是项目目标能否实现的关键。 1.1 学会放权 任何人都不能掌握所有的知识和技能,要敢于相信别人,让别人去做。 放权就要选择最…...
day22 ● 235. 二叉搜索树的最近公共祖先 ● 701.二叉搜索树中的插入操作 ● 450.删除二叉搜索树中的节点
问题: ● 235. 二叉搜索树的最近公共祖先 ● 701.二叉搜索树中的插入操作 ● 450.删除二叉搜索树中的节点 首先,二叉搜索树是一种常见的数据结构,它具有以下特点: 每个节点最多有两个子节点,分别为左子节点和右子节…...
ChatGPT 这个风口,普通人怎么抓住?
最近在测试ChatGPT不同领域的变现玩法,有一些已经初见成效,接下来会慢慢分享出来。 今天先给大家分享一个,看完就能直接上手的暴力引流玩法。 所需工具: 1)ChatGPT(最好是plus版,需要保证快速…...
HP-Socket开发者技能认证考试大纲更新全指南:周期解析与参与攻略
HP-Socket开发者技能认证考试大纲更新全指南:周期解析与参与攻略 【免费下载链接】HP-Socket High Performance TCP/UDP/HTTP Communication Component 项目地址: https://gitcode.com/gh_mirrors/hp/HP-Socket HP-Socket作为高性能TCP/UDP/HTTP通信组件&…...
coze-loop新手指南:无需配置,开箱即用的代码优化工具
coze-loop新手指南:无需配置,开箱即用的代码优化工具 1. 为什么你需要一个代码优化助手 想象一下这样的场景:你刚刚写完一段功能代码,运行起来没问题,但总觉得哪里不够完美。可能是执行速度不够快,或者代…...
实践指南:如何使用Cisco DefenseClaw保护你的AI Agent安全
一、背景:AI Agent安全面临的新挑战 最近,开源AI代理框架OpenClaw遭遇了大规模供应链攻击,超过800个恶意技能被植入ClawHub技能市场。这个事件被命名为"ClawHavoc",它暴露了AI Agent生态的安全漏洞。 作为开发者&#x…...
跨域突围与全栈架构演进:从Vite本地代理到Nginx部署+Next.js BFF层实战
摘要:前面10篇博客,我们从SPA架构、React核心Hook、TS类型系统、组件化封装、性能优化,一步步吃透了中后台系统的前端开发全流程,完成了从前端入门到熟练开发的进阶。但想要从“只会写页面的码农”,升级为“懂架构、懂…...
SGP30传感器数据不准?可能是你的I2C时序和初始化搞错了(避坑指南)
SGP30传感器数据异常排查指南:从硬件设计到软件调试的完整解决方案 1. 硬件设计中的常见陷阱与优化方案 SGP30作为一款高精度环境传感器,其硬件设计细节直接影响数据可靠性。许多开发者遇到的首要问题往往源于电路设计阶段被忽视的关键参数。 电源稳定性…...
OpenClaw排错指南:Qwen3-VL:30B部署常见问题与解决方案
OpenClaw排错指南:Qwen3-VL:30B部署常见问题与解决方案 1. 问题背景与排查准备 上周我在本地部署Qwen3-VL:30B模型并接入OpenClaw时,遇到了不少"坑"。这个号称最强的多模态大模型确实强大,但在私有化部署过程中,从模型…...
告别“人工智障”!OpenClaw + 大模型:打造真正能“看懂、想通、干成”的机械臂智能体
写在前面 在机器人圈子里,有个心照不宣的痛点:机械臂越来越便宜,但让它“听话”却越来越难。 传统的示教编程(Teaching Pendant)太慢,改个产品就得重教一遍;视觉定位(Vision Guided&…...
EmbeddingGemma-300m在Mathtype公式的语义理解中的应用
EmbeddingGemma-300m在Mathtype公式的语义理解中的应用 1. 引言 数学公式的语义理解一直是自然语言处理领域的挑战性任务。传统的文本嵌入模型在处理复杂的数学表达式时往往力不从心,无法准确捕捉公式背后的数学含义和逻辑关系。EmbeddingGemma-300m作为Google最新…...
新手福音:通过快马平台生成带注释的nap自动化运维脚本快速入门
作为一个刚接触网络自动化运维的新手,第一次看到"深圳网络自动化运维nap"这个概念时,整个人都是懵的。各种专业术语、复杂的协议和库让我望而却步,直到发现了InsCode(快马)平台,才真正找到了入门的好方法。 为什么选择n…...
通义千问3-Reranker-0.6B性能调优:提升推理速度的3种方法
通义千问3-Reranker-0.6B性能调优:提升推理速度的3种方法 1. 引言 如果你正在使用通义千问3-Reranker-0.6B模型,可能会遇到推理速度不够理想的情况。特别是在处理大量文本排序任务时,等待时间可能会影响整体工作效率。 其实,这…...
