一、异常的基本概念

在Python中,异常是指程序执行过程中发生的错误。当程序遇到错误时,会抛出异常,如果不处理这些异常,程序会终止执行。

二、异常处理的基本语法

1. try-except语句

1
2
3
4
5
6
try:
# 可能会抛出异常的代码
result = 10 / 0
except ZeroDivisionError:
# 处理ZeroDivisionError异常
print("除数不能为零")

2. 捕获多个异常

1
2
3
4
5
6
7
8
9
10
try:
# 可能会抛出异常的代码
result = int(input("请输入一个数字"))
print(10 / result)
except ZeroDivisionError:
# 处理ZeroDivisionError异常
print("除数不能为零")
except ValueError:
# 处理ValueError异常
print("请输入有效的数字")

3. 捕获所有异常

1
2
3
4
5
6
try:
# 可能会抛出异常的代码
result = 10 / 0
except Exception as e:
# 处理所有异常
print(f"发生了错误:{e}")

4. else子句

如果try块中没有发生异常,会执行else子句:

1
2
3
4
5
6
7
8
9
try:
# 可能会抛出异常的代码
result = 10 / 2
except ZeroDivisionError:
# 处理ZeroDivisionError异常
print("除数不能为零")
else:
# 没有发生异常时执行
print(f"结果是:{result}")

5. finally子句

无论是否发生异常,finally子句都会执行:

1
2
3
4
5
6
7
8
9
try:
# 可能会抛出异常的代码
result = 10 / 0
except ZeroDivisionError:
# 处理ZeroDivisionError异常
print("除数不能为零")
finally:
# 无论是否发生异常都会执行
print("执行完毕")

三、异常的层次结构

Python的异常是有层次结构的,所有异常都继承自BaseException类。常见的异常层次结构如下:

  • BaseException
    • Exception
      • ArithmeticError
        • ZeroDivisionError
      • LookupError
        • KeyError
        • IndexError
      • ValueError
      • TypeError
      • ImportError
    • SystemExit
    • KeyboardInterrupt

四、自定义异常

你可以通过继承Exception类来创建自定义异常:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyCustomError(Exception):
"""自定义异常"""
pass

def process_data(data):
if not data:
raise MyCustomError("数据不能为空")
# 处理数据...

# 使用自定义异常
try:
process_data(None)
except MyCustomError as e:
print(f"发生了自定义异常:{e}")

五、异常处理的最佳实践

1. 只捕获你能处理的异常

不要捕获所有异常,只捕获你知道如何处理的异常:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 不好的做法
try:
# 代码

except Exception:
# 捕获所有异常,可能会掩盖真正的问题
pass

# 好的做法
try:
# 代码

except (ZeroDivisionError, ValueError) as e:
# 只捕获特定的异常
print(f"发生了已知错误:{e}")

2. 保持异常处理的简洁

异常处理代码应该简洁明了,只处理必要的逻辑:

1
2
3
4
5
6
try:
result = 10 / x
except ZeroDivisionError:
# 简洁地处理异常
print("除数不能为零")
result = 0

3. 使用finally释放资源

当你使用需要手动释放的资源(如文件、网络连接等)时,应该使用finally子句来确保资源被释放:

1
2
3
4
5
6
7
file = None
try:
file = open('file.txt', 'r')
# 处理文件
finally:
if file:
file.close()

或者使用with语句,它会自动处理资源的释放:

1
2
3
with open('file.txt', 'r') as file:
# 处理文件
# 文件会自动关闭

4. 抛出有意义的异常

当你抛出异常时,应该提供有意义的错误信息,以便调用者能够理解发生了什么问题:

1
2
3
4
def divide(a, b):
if b == 0:
raise ZeroDivisionError("除数不能为零")
return a / b

六、实际应用示例

1. 处理文件操作异常

1
2
3
4
5
6
7
8
9
10
try:
with open('file.txt', 'r') as f:
content = f.read()
print(content)
except FileNotFoundError:
print("文件不存在")
except PermissionError:
print("没有权限读取文件")
except Exception as e:
print(f"发生了其他错误:{e}")

2. 处理网络请求异常

1
2
3
4
5
6
7
8
9
10
11
12
import requests

try:
response = requests.get('https://www.example.com')
response.raise_for_status() # 检查HTTP状态码
print(response.text)
except requests.ConnectionError:
print("网络连接失败")
except requests.HTTPError as e:
print(f"HTTP错误:{e}")
except Exception as e:
print(f"发生了其他错误:{e}")

3. 处理数据库操作异常

1
2
3
4
5
6
7
8
9
10
11
12
13
import sqlite3

try:
conn = sqlite3.connect('database.db')
cursor = conn.cursor()
cursor.execute('SELECT * FROM users')
results = cursor.fetchall()
print(results)
except sqlite3.Error as e:
print(f"数据库错误:{e}")
finally:
if conn:
conn.close()