python和java的异常处理机制的对比

当你在编写程序时,可能由于人为或其它因素导致发生异常后,如果不对异常处理,程序就无法继续执行。Python语言中也有自己的异常处理,下面我们先看下Java中的异常处理,然后再对比Python中的异常处理,其实它们都大同小异。java 中的异常处理我们不做过多介绍,只是为了和python的异常处理做对比,加深理解。

一、.Java 中的异常处理

java 中 处理异常有五个关键字:try catch finally throw throws 
try:将可能发生的异常存放到try块中 
catch:对异常进行捕获 
finally:无论是否出现异常都执行 
throw:在方法体中抛出异常 
throws:在方法上抛出异常

java 中对异常的处理更加严谨,异常的种类及结构如下

这里写图片描述

java 中 所有异常的父类为Throwable,Throwable 中有两个重要的子类:Error(错误)和 Exception(异常)

Error 是不可恢复的异常,比如:JVM 溢出。 
Exception 又分为两种异常:检查时异常和运行时异常。 
检查时异常的特点是需要客户程序员捕获异常(try)或抛出异常(throws)让调用着来处理,比如在IO编程、线程、xml解析应用中的异常都为检查时异常,需要我们手动捕获或抛出异常。

// 检查时异常
public static  void main(String[] args){
    try {
        System.in.read();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

运行时异常指的是所有的RuntimeException及其子类,特点是无须客户程序员try或throws

// 运行时异常
public static void main(String[] args){
    args[1] = "exception"; // 数组下标访问越界
}

在实际编程中,有时我们会自己定义一些异常来对异常进行处理,java 中 自定义检查时异常需要继承Exception 类并覆盖方法,自定义运行时异常需要继承 RuntimeException 并覆盖方法。

// 自定义检查时异常
public class MyException extends Exception {
    public MyException() {
        super();
    }

    public MyException(String message) {
        super(message);
    }

    public MyException(String message, Throwable cause) {
        super(message, cause);
    }

    public MyException(Throwable cause) {
        super(cause);
    }

    protected MyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }

    // 测试(需要捕获或抛出异常)
    public static  void main(String[] args){
        try {
            throw new MyException("自定义检查时异常");
        } catch (MyException e) {
            e.printStackTrace();
        }
    }
}
// 自定义运行时异常
public class MyRuntimeException extends  RuntimeException {
    public MyRuntimeException() {
        super();
    }

    public MyRuntimeException(String message) {
        super(message);
    }

    public MyRuntimeException(String message, Throwable cause) {
        super(message, cause);
    }

    public MyRuntimeException(Throwable cause) {
        super(cause);
    }

    protected MyRuntimeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }

    // 测试(不需要捕获或抛出异常)
    public static  void main(String[] args){
        throw new MyRuntimeException("自定义运行时异常");
    }
}

二、Python 中的异常处理

python 中的异常处理相比java来说,要简单一些,python 中使用四个关键字来处理异常 
try:捕获异常,类似于 java 中的 try 
except:处理异常,类似于 java 中的 catch 
finally:不管是否捕获到异常都会被执行,类似于 java 中 的 finally 
raise:抛出异常,类似于 java 中的 throw

异常执行流程: 
      try块存放可能出现的异常代码,如果没有异常发生,忽略except子句,try子句执行后结束;如果在执行try子句的过程中发生了异常,那么try子句余下的部分将被忽略,如果异常的类型和 except 之后的名称相符,那么对应的except子句将被执行。最后执行 try 语句之后的代码。不管try在执行时,是否发生了异常,finally块中的内容都会被执行。

python是一种解释型语言,也就是说没有编译,所有它没有检查时异常,只有运行时异常,python 中常见异常如下

异常描述
AssertionErrorassert(断言)语句失败
AttributeError访问一个对象没有的属性,比如foo.x ,foo没有x这个属性。
IOError输入/输出异常,基本上是无法打开文件
ImportError无法引入模块或者包,基本上是路径问题
IndentationError语法错误,代码没有正确对齐
IndexError下标访问越界,比如当x只有三个元素,却试图访问x[5]
KeyError试图访问字典里不存在的键
KerboardInterruptCtrl + C 被按下
NameError使用一个还未被赋值予对象的变量
SyntaxErrorPython代码非法,代码不能解释
TypeError传入对象类型与要求的不符
UnboundLocalError试图访问一个还未被设置的局部变量,基本上是由于另一个同名的全局变量,导致你以为正在访问它
ValueError传入一个调用者不期望的值,即使值的类型是正确的



python 中经常用 print() 来打印输出内容,使用print()抛出异常,示例如下

print(5/0)

这里写图片描述

1.raise 抛出异常

示例:输入一个数字,如果不是数字则抛出异常ValueError

inputValue=input("请输入一个数字:")
type(inputValue)
if inputValue.isdigit():
    print(inputValue)
else:
    raise ValueError

运行结果1: 
请输入一个数字:1 
1

运行结果2: 
请输入一个数字:hello 
Traceback (most recent call last): 
File “C:\Users\Administrator\Desktop\test.py”, line 6, in 
raise ValueError 
ValueError 

2.try…except…

我们在编写程序时,可能会出现一些错误或异常,如果不进行处理那么程序就会中止执行,示例如下,访问字符串中下标为20的字符时,会抛出IndexError异常

str = "hello python"
print(str[20])  # IndexError: string index out of range

运行结果: 
Traceback (most recent call last): 
File “E:/code/workspace_python/class/python_day03/testError.py”, line 2, in 
print(str[20]) # IndexError: string index out of range 
IndexError: string index out of range 

改写示例,使用 try…except… 处理异常

str = "hello python"
try:
    print(str[20])
except IndexError:
    print('error...')

再次运行程序,发生异常后会打印 error…

3.try….except…else

str = "hello python"
try:
    print(str[10])
except IndexError:
    print('error...')
else:
    print('no error...')

运行结果: 

no error…

将 str[10] 该为str[20],else块中的内容将不会执行,运行结果为:error…

4.try…except…finally

我们通过一个小案例来看下 try…except…finally 是如何处理异常的,输入两个数字然后做除法运算,将可能发生的异常代码放到 try 块中,except 块中对捕获到的异常继续处理

try:
    num1 = int(input("请输入第一个数:"))
    num2 = int(input("请输入第二个数:"))
    result = num1 / num2
    print("{0} / {1} = num{2}".format(num1, num2, result))
except ValueError as e:
    print("ValueError:{0}".format(e))
finally:
    print("bye bye");

运行结果1: 
请输入第一个数:10 
请输入第二个数:5 
10 / 5 = num2.0 
bye bye

运行结果2:第二个数字为字符h,抛出异常ValueError 
请输入第一个数:1 
请输入第二个数:h 
ValueError:invalid literal for int() with base 10: ‘h’ 
bye bye

运行结果3:除数为0,抛出异常ZeroDivisionError 
请输入第一个数:1 
请输入第二个数:0 
Traceback (most recent call last): 
File “E:/code/workspace_python/class/python_day03/testError.py”, line 4, in 
result = num1 / num2 
ZeroDivisionError: division by zero 

bye bye

运行结果3中抛出了一个ZeroDivisionError异常,我们并没有对这个异常做处理,异常处理时可以有多个except子句,修改上述代码

try:
    num1 = int(input("请输入第一个数:"))
    num2 = int(input("请输入第二个数:"))
    result = num1 / num2
    print("{0} / {1} = num{2}".format(num1, num2, result))
except ValueError as e:
    print("ValueError:{0}".format(e))
except ZeroDivisionError as e:
    print("ZeroDivisionError:{0}".format(e))
finally:
    print("bye bye");

运行结果: 
请输入第一个数:1 
请输入第二个数:0 
ZeroDivisionError:division by zero 
bye bye

一个 try 语句可能包含多个except子句,分别来处理不同的特定的异常。最多只有一个分支会被执行,当有多个except子句时,可以将异常写在一个元祖里,改写上述代码

try:
    num1 = int(input("请输入第一个数:"))
    num2 = int(input("请输入第二个数:"))
    result = num1 / num2
    print("{0} / {1} = num{2}".format(num1, num2, result))
except (ValueError, ZeroDivisionError)as e:
    print("Error:{0}".format(e))
finally:
    print("bye bye");

运行结果同上

5.传递异常

异常处理时,有时候我们在函数或方法内捕获到了异常,但是又想重新引发它(传递异常),可以使用不带参数的raise语句实现,代码如下

class Mcl:
    def calc(self, num1, num2):
        try:
            result = num1 / num2
            print("{0} / {1} = {2}".format(num1, num2, result))
            return num1 / num2
        # 捕获到异常后不做处理
        except ZeroDivisionError as e:
            raise
app = Mcl()
app.calc(10, 2)
# 运行结果
# 10 / 2 = 5.0app = Mcl()
app.calc(1, 0)
# 运行结果(抛出异常):ZeroDivisionError: division by zero

6.自定义异常

class MyError(Exception):
    # 覆盖Exception的__init__()方法
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)

raise MyError("自定义异常!")

运行结果 
Traceback (most recent call last): 
File “E:/code/workspace_python/class/python_day03/testError.py”, line 7, in 
raise MyError(“自定义异常!”) 
main.MyError: ‘自定义异常!’ 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值