乔克视界 乔克视界
首页
  • 运维
  • 开发
  • 监控
  • 安全
  • 随笔
  • Docker
  • Golang
  • Python
  • AIOps
  • DevOps
  • 心情杂货
  • 读书笔记
  • 面试
  • 实用技巧
  • 博客搭建
友链
关于
收藏
  • 分类
  • 标签
  • 归档

乔克

云原生爱好者
首页
  • 运维
  • 开发
  • 监控
  • 安全
  • 随笔
  • Docker
  • Golang
  • Python
  • AIOps
  • DevOps
  • 心情杂货
  • 读书笔记
  • 面试
  • 实用技巧
  • 博客搭建
友链
关于
收藏
  • 分类
  • 标签
  • 归档
  • Docker

  • Golang

  • AIOps

  • Python

    • 基础知识

      • Python之链表
      • Python 之类的初识
      • Python之函数式编程
      • Python之匿名函数
      • Python之自定义函数
      • Python之异常处理
        • 一、错误和异常
        • 二、异常处理
        • 三、自定义异常
        • 四、异常的使用场景和注意点
        • 五、总结
      • Python之条件与循环
      • Python之列表生成式
      • Python之生成器
      • Python之装饰器
      • Python之迭代器
      • Python之进程、线程、协程
      • Python之深浅拷贝
      • Python之反射
      • Python之并发编程
      • Python之垃圾回收机制
      • Python之断言assert
      • Python之上下文管理器和with语句
      • Python中JSON的对应关系
      • Python之单例模式
    • Django框架

    • 其他

  • DevOps

  • 专栏
  • Python
  • 基础知识
乔克
2025-07-19
目录

Python之异常处理

# 一、错误和异常

所谓的错误就是语法错误,也就是代码不符合 python 规范,比如:

for i in range(0,10)
	print(i)
1
2

for 循环的条件后来漏掉了":",所以程序运行的时候就会输出:invalid syntax。

而异常则是语法正确,符合 python 的语法规范,所以程序可以执行,只是在执行的过程中出现错误,抛出异常。如下:

>>> 1/0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
>>> order * 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'order' is not defined
>>> 1 + [1,2]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'list'
>>>
1
2
3
4
5
6
7
8
9
10
11
12
13

显然语法是没有问题的,只是 0 不能作为除数,也不能使用未定义的变量,所以在执行过程中就会抛出异常,上面的 ZeroDivisionError,NameError,TypeError 就是常见的异常类型。

实际中还有很多的异常类型,详细可以见官方介绍 (opens new window)。

# 二、异常处理

在处理异常的时候,我们通常都用 try....except....来处理。比如:

try:
    s = input('please enter two numbers separated by comma: ')
    num1 = int(s.split(',')[0].strip())
    num2 = int(s.split(',')[1].strip())
except ValueError as err:
    print('Value Error: {}'.format(err))

print('continue')
1
2
3
4
5
6
7
8

用户输入逗号相隔的两个整型数字,如果输入的不一致,就会跳出 try,抛出异常 ValueError,再继续后续输出 continue。这种情况是规定了异常类型是 ValueError,如果异常类型匹配,则会输出'Value Error: ....',然后输出下面的 continue,如果异常不匹配,程序依然会跳出 try,但是是直接退出了,并不会打印下面的 continue。如下所示:

## 异常类型匹配
please enter two numbers separated by comma: 1,2
continue

## 异常类型不匹配
please enter two numbers separated by comma: 1
Traceback (most recent call last):
  File "c:\Users\Joker\.vscode\extensions\ms-python.python-2019.4.12954\pythonFiles\ptvsd_launcher.py", line 43, in <module>
    main(ptvsdArgs)
  File "c:\Users\Joker\.vscode\extensions\ms-python.python-2019.4.12954\pythonFiles\lib\python\ptvsd\__main__.py", line 410, in main
    run()
  File "c:\Users\Joker\.vscode\extensions\ms-python.python-2019.4.12954\pythonFiles\lib\python\ptvsd\__main__.py", line 291, in run_file
    runpy.run_path(target, run_name='__main__')
  File "D:\software\python3\lib\runpy.py", line 263, in run_path
    pkg_name=pkg_name, script_name=fname)
  File "D:\software\python3\lib\runpy.py", line 96, in _run_module_code
    mod_name, mod_spec, pkg_name, script_name)
  File "D:\software\python3\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "e:\Joker\工作日志\个人文件\python_scripts\Python\test.py", line 219, in <module>
    num2 = int(s.split(',')[1].strip())
IndexError: list index out of range
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

由上可知,如果只写一个异常类型的局限性很大,因为不一定所有的异常类型都会考虑到,所以我们还可以采用定义多种异常来处理,如下:

try:
    s = input('please enter two numbers separated by comma: ')
    num1 = int(s.split(',')[0].strip())
    num2 = int(s.split(',')[1].strip())
except ValueError as err:
    print('Value Error: {}'.format(err))
except IndexError as err:
    print('Index Error: {}'.format(err))

print('continue')
1
2
3
4
5
6
7
8
9
10

也可以写成下面这种形式,效果是一样的:

try:
    s = input('please enter two numbers separated by comma: ')
    num1 = int(s.split(',')[0].strip())
    num2 = int(s.split(',')[1].strip())
except (ValueError,IndexError) as err:
    print('Value Error: {}'.format(err))

print('continue')
1
2
3
4
5
6
7
8

这种写法只要满足任意一个异常即可。但是如果异常太多,如果把全部异常都写上,那么就会造成代码非常的繁重,所以我们会用 Exception 来处理其他异常,它可以匹配任意异常,如下:

try:
    s = input('please enter two numbers separated by comma: ')
    num1 = int(s.split(',')[0].strip())
    num2 = int(s.split(',')[1].strip())
except ValueError as err:
    print('Value Error: {}'.format(err))
except IndexError as err:
    print('Index Error: {}'.format(err))
except Exception as err:						## 这里也可以写成:except: 表示与任意异常相匹配
    print('Exception: {}'.format(err))

print('continue')
1
2
3
4
5
6
7
8
9
10
11
12

注意:如果程序中定义了多个 except,最多只有一个 except 被执行。换句话说,如果多个 except 都与实际异常相匹配,则只有最前面的会被执行,其他的都会忽略。

异常处理中,还有一个常用的用法:finally,经常和 try,except 放在一起使用,它表示无论是什么异常,finally 下的语句都会被执行,哪怕 try,except 里有 return 语句。

一般场景如下,读取文件操作:

import sys
try:
    f = open('file.txt', 'r')
    .... ## some data processing
except OSError as err:
    print('OS error: {}'.format(err))
except:
    print('Unexpected error:', sys.exc_info()[0])
finally:
    f.close()
1
2
3
4
5
6
7
8
9
10

在这段代码中,不论 try,except 是怎样,finally 中的 f.close()都会被执行,确保文件的完整性。

一般情况下,我们会把无论如何都要执行的语句放在 finally 中。

# 三、自定义异常

异常也可以自定义,如下:

class MyInputError(Exception):
    """Exception raised when there're errors in input"""
    def __init__(self, value): ## 自定义异常类型的初始化
        self.value = value
    def __str__(self): ## 自定义异常类型的 string 表达形式
        return ("{} is invalid input".format(repr(self.value)))

try:
    raise MyInputError(1) ## 抛出 MyInputError 这个异常
except MyInputError as err:
    print('error: {}'.format(err))
1
2
3
4
5
6
7
8
9
10
11

在实际工作中,如果内置的异常类型不能满足生产中需要的时候,就可以自定义异常,不过大多数情况下内置的异常类型足够用了。

# 四、异常的使用场景和注意点

通常来说,我们不确定一段代码是否能够成功执行,就需要在这些地方进行异常处理。

举一个例子:大型网站的后台,需要针对用户发送的请求返回相应的记录,用户数据往往存储在 key-value 的数据库中,每次请求过来,我们会拿到用户 ID,然后在数据库中读出所在行,返回相应的记录,而数据返回的原始数据,往往是 json string 形式,这时候往往就需要我们对数据进行 decode,这时候往往你会想到以下方法:

import json
raw_data = queryDB(uid) ## 根据用户的 id,返回相应的信息
data = json.loads(raw_data)
1
2
3

但是,上面这种情况就必须保证数据是完全正常的,不然就会报错,这时候加异常就变得很重要了,如下形式:

import json
try:
    raw_data = queryDB(uid) ## 根据用户的 id,返回相应的信息
    data = json.loads(raw_data)
except JSONDecodeError as err:
    print('JSONDecodeError: {}'.format(err))

1
2
3
4
5
6
7

所以异常处理在代码中是非常重要的,但是,我们也不能滥用异常处理,比如:

d = {'name': 'jason', 'age': 20}
try:
    value = d['dob']
except KeyError as err:
    print('KeyError: {}'.format(err))

1
2
3
4
5
6

这样的写法没什么毛病,但是给人的感觉就很傻逼,完全没这个必要。这种时候就完全没必要做异常处理。

# 五、总结

(1)、异常,通常是指程序运行过程种遇到错误,终止并退出,我们通常会使用 try....except....语法去处理异常,这样程序就不会被终止,仍然会继续执行;

(2)、处理异常时,如果有必须执行的语句,则将这个语句放在 finally 中;

(3)、异常处理,通常用在不确定某段代码是否能够成功执行,也无法轻易判断的情况下,比如数据库连接、读取等等,正常的 flow-control 逻辑,就不需要使用异常处理,直接用条件语句就能解决。

作者:乔克

本文链接:https://jokerbai.com

版权声明:本博客所有文章除特别声明外,均采用 署名-非商业性-相同方式共享 4.0 国际 (CC-BY-NC-SA-4.0) 许可协议。转载请注明出处!

上次更新: 2025/07/19, 11:33:23
Python之自定义函数
Python之条件与循环

← Python之自定义函数 Python之条件与循环→

最近更新
01
使用 Generic Webhook Trigger 触发 Jenkins 多分支流水线自动化构建
07-19
02
使用Zadig从0到1实现持续交付平台
07-19
03
基于Jira的运维发布平台
07-19
更多文章>
Theme by Vdoing | Copyright © 2019-2025 乔克 | MIT License | 渝ICP备20002153号 |
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式