python进阶系列 - 09 异常 Exception

642 阅读6分钟

凡事即可错,但总有补救办法!

在编写Python程序时,经常回因为错误导致程序立即终止。在Python中,错误可以是语法错误异常

接下来我们将介绍python的常见异常以及如何处理错误,主要覆盖一下知识点:

  • 语法错误 vs. 异常
  • 如何引发异常
  • 如何处理异常
  • 最常见的内置异常
  • 如何定义你自己的异常

语法错误 - Syntax Errors

语法错误发生在解析器检测到一个语法错误的语句。 一个语法错误可以是一个拼写错误,缺少括号,没有换行(请看下面的代码),或错误的缩进(这将实际上抛出它自己的IndentationError,但是它是一个SyntaxError 的子类)。

代码:

a = 5
print(a)

结果:

  File "/usercode/main.py", line 1
    a = 5 print(a)
              ^
SyntaxError: invalid syntax

异常 - Exceptions

即使语句是正确的,也可能在执行时引发错误。 这是一个异常错误。有几个不同的错误类,例如尝试将一个数字和字符串相加将引发一个TypeError

代码:

a = 5 + '10'

结果:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/usercode/main.py in <module>
----> 1 a = 5 + '10'

TypeError: unsupported operand type(s) for +: 'int' and 'str'

抛出异常 - Raising an Exception

如果你想在某个条件发生时强制抛出异常,可以使用raise关键字。

代码:

x = -5
if x < 0:
    raise Exception('x不可以是负数')

结果:

---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
/usercode/main.py in <module>
      1 x = -5
      2 if x < 0:
----> 3     raise Exception('x不可以是负数')

Exception: x不可以是负数

你也可以使用assert语句,它会在你的断言为为真时抛出AssertionError。 这样,你可以主动测试一些条件,必须被满足而不是等待你的程序意外地崩溃。 assert也被用于单元测试

代码:

x = -5
assert (x >= 0), 'x不是负数'
# --> 在x不是负数时,抛出AssertionError

结果:

---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
/usercode/main.py in <module>
      1 x = -5
----> 2 assert (x >= 0), 'x不是负数'
      3 # --> 在x不是负数时,抛出AssertionError

AssertionError: x不是负数

处理异常 - Handling Exceptions

你可以使用try-except块来捕获和处理异常。 如果你捕获了异常,那么程序不会终止,可以继续执行。

# 这将捕获所有可能的异常
try:
    a = 5 / 0
except:
    print('发生了一些错误!')
# 你也可以捕获异常的类型
try:
    a = 5 / 0
except Exception as e:
    print(e)
# 它是一个好习惯,指定你想捕获的异常类型
# 因为,你必须知道可能的错误

try:
    a = 5 / 0
except ZeroDivisionError:
    print('仅仅捕获了除零异常,而没有捕获其他的异常。')
# 你可以在一个try块中运行多个语句,并且捕获不同的可能的异常
try:
    a = 5 / 1  # 注意:没有ZeroDivisionError这里
    b = a + '10'
except ZeroDivisionError as e:
    print('除零错误:', e)
except TypeError as e:
    print('类型错误:', e)

结果:

发生了一些错误!
division by zero
仅仅捕获了除零异常,而没有捕获其他的异常。
类型错误: unsupported operand type(s) for +: 'float' and 'str'

else 子句

你可以使用else语句,它在没有发生异常时执行。

代码:

try:
    a = 5 / 1
except ZeroDivisionError as e:
    print('除零错误:', e)
else:
    print('一切正常!')

结果:

一切正常!

finally 子句

你可以使用finally语句,它总是会执行,无论是否发生异常。 这是为了做一些清理工作。

try:
    a = 5 / 1  # 注意:没有ZeroDivisionError这里
    b = a + '10'
except ZeroDivisionError as e:
    print('发生了除零错误:', e)
except TypeError as e:
    print('发生了类型错误:', e)
else:
    print('一切正常!')
finally:
    print('无论是否发生异常,都会执行的代码')

结果:

发生了类型错误: unsupported operand type(s) for +: 'float' and 'str'
无论是否发生异常,都会执行的代码

内建异常 - built-in Exceptions

你可以在官网查看所有的内建的异常,以下是常见的异常:

  • ImportError:如果一个模块不能被导入
  • NameError:如果你尝试使用一个未定义的变量
  • FileNotFoundError:如果你尝试打开一个不存在的文件或者你指定了错误的路径
  • ValueError:当一个操作或者函数接收到一个合适的类型的参数,但是参数的值不合适时,比如尝试从一个列表中移除一个不存在的值
  • TypeError:当一个操作或者函数应用了一个不适合的类型的对象时,比如尝试从一个列表中移除一个不存在的值
  • IndexError:如果你尝试访问一个不存在的索引
  • KeyError:如果你尝试访问一个不存在的键

代码:

# 定义一个函数,打印内置异常
def printErr(code, message):
    print(f">>>{message} 演示:\n")
    try:
        exec(code)
    except Exception as e:
        print(f""{code}": {e}")


printErr("import not_exist_module", "模块不存在")
printErr("a=not_exist_variable", "变量不存在")
printErr("f = open('not_exist_file.txt')", "文件不存在")
printErr("a=[0,1,2];a.remove(3)", "值错误")
printErr("a = 5 + '10'", "类型错误")
printErr("a = [0, 1, 2]; value = a[5]", "索引错误")
printErr("my_dict = {'name': 'Max', 'city': 'Boston'}; age = my_dict['age']", "键错误")

结果:

 >>> import not_exist_module: 模块不存在
No module named 'not_exist_module'

 >>> a=not_exist_variable: 变量不存在
name 'not_exist_variable' is not defined

 >>> f = open('not_exist_file.txt'): 文件不存在
[Errno 2] No such file or directory: 'not_exist_file.txt'

 >>> a=[0,1,2];a.remove(3): 值错误
list.remove(x): x not in list

 >>> a = 5 + '10': 类型错误
unsupported operand type(s) for +: 'int' and 'str'

 >>> a = [0, 1, 2]; value = a[5]: 索引错误
list index out of range

 >>> my_dict = {'name': 'Max', 'city': 'Boston'}; a = my_dict['age']: 键错误
'age'

自定义异常 - Define your own Exceptions

你也可以定义你自己的异常类,但应该继承自内建的Exception类。

大多数异常都以Error结尾的,与标准异常相似,异常类也可以定义为任何类型, 但是通常都很简单的,只提供一些属性,允许处理程序提取错误的信息。

代码:

# 定义一个自定义异常类
class ValueTooHighError(Exception):
    pass


# 或者给处理程序添加更多的信息
class ValueTooLowError(Exception):
    def __init__(self, message, value):
        self.message = message
        self.value = value


def test_value(a):
    if a > 1000:
        raise ValueTooHighError('值太大了')
    if a < 5:
        raise ValueTooLowError('值太小了', a)  # 注意这里的构造函数参数为2个
    return a


try:
    test_value(1)
except ValueTooHighError as e:
    print(e)
except ValueTooLowError as e:
    print(e.message, '值为:', e.value)

结果:

值太小了 值为: 1

总结

本文简要介绍python常见的错误异常,以及如何对异常进行处理。异常是编程中百分百会遇到的,正确的捕获异常及处理,可以让程序变的更加的健壮!

感谢你阅读本文。如果觉得这篇文章对你有帮助,欢迎大家点赞、收藏、支持!

pythontip 出品,Happy Coding!

公众号: 夸克编程