目录
try语句的结构与作用
基本结构
try:
# 可能引发异常的代码块
except ExceptionType1:
# 处理ExceptionType1类型的异常
except ExceptionType2:
# 处理ExceptionType2类型的异常
else:
# 如果没有异常发生,执行此块
finally:
# 无论是否发生异常,都会执行此块
各部分作用
- try块:包含可能引发异常的代码
- except块:捕获并处理特定类型的异常
- else块:当try块没有引发异常时执行
- finally块:无论是否发生异常都会执行,常用于资源清理
基础异常处理
一、HTTP请求异常处理
解决思路:
- 使用
requests
库发送HTTP请求。 - 通过
response.raise_for_status()
方法检查HTTP响应状态码,若状态码为4xx或xx,则引发HTTPError
异常。 - 捕获
HTTPError
、Timeout
和RequestException
异常,分别处理HTTP错误、请求超时和通用网络异常。
命令部署:
import requests
try:
response = requests.get('https://api.example.com/nonexistent', timeout=3)
response.raise_for_status()
except requests.exceptions.HTTPError as http_err:
print(f'HTTP错误: {http_err}') # 捕获xx/5xx状态码
except requests.exceptions.Timeout:
print('请求超时') # 超过秒未响应
except requests.exceptions.RequestException as err:
print(f'请求异常: {err}') # 通用网络异常
二、数据库操作异常
解决思路:
- 使用SQLAlchemy执行数据库查询。
- 捕获
NoResultFound
异常,处理查询结果为空的情况。 - 捕获
SQLAlchemyError
异常,处理其他数据库错误,并回滚事务。
命令部署:
from sqlalchemy.exc import SQLAlchemyError, NoResultFound
try:
user = db.session.query(User).filter_by(id=).one()
except NoResultFound:
print('查询结果不存在') # 处理空结果
except SQLAlchemyError as e:
db.session.rollback() # 必须回滚事务
print(f'数据库错误: {e}')
三、表单验证异常
解决思路:
- 使用Flask-WTF进行表单验证。
- 若验证失败,则引发
ValidationError
异常。 - 捕获
ValidationError
和IntegrityError
异常,分别处理字段验证失败和唯一约束违反的情况。
注意:IntegrityError
需要在from sqlalchemy.exc import IntegrityError
中导入,但原代码中未显示导入,这里假设已正确导入。
命令部署:
from wtforms.validators import ValidationError
from sqlalchemy.exc import IntegrityError # 假设已正确导入
try:
if not form.validate_on_submit():
raise ValidationError('字段验证失败')
user = User(form.username.data, form.password.data)
db.session.add(user)
db.session.commit()
except ValidationError as ve:
print(f'验证失败: {ve}') # 处理字段规则违反
except IntegrityError:
db.session.rollback() print('用户名已存在') # 唯一约束违反
四、权限校验异常
解决思路:
- 在Django视图中检查用户权限。
- 若用户非超级管理员,则引发
PermissionDenied
异常。 - 捕获
PermissionDenied
异常,返回3 Forbidden响应。
命令部署:
from django.core.exceptions import PermissionDenied
from django.http import HttpResponse
from django.shortcuts import render # 假设已正确导入
def admin_view(request):
try:
if not request.user.is_superuser:
raise PermissionDenied
return render(request, 'admin.html')
except PermissionDenied:
return HttpResponse('3 Forbidden', status=)
五、第三方API异常
解决思路:
- 调用第三方支付接口创建订单。
- 检查订单响应状态码,若不为
SUCCESS
,则引发ThirdPartyAPIError
异常(假设已自定义该异常类)。 - 捕获
ThirdPartyAPIError
和ConnectionResetError
异常,分别处理业务逻辑错误和网络层错误。
注意:ThirdPartyAPIError
需要在代码中自定义,原代码中未显示定义,这里假设已正确定义。
命令部署:
class ThirdPartyAPIError(Exception):
pass # 假设已自定义该异常类
try:
resp = pay_client.create_order(
amount=,
currency='CNY',
timeout=0
)
if resp['code' != 'SUCCESS':
raise ThirdPartyAPIError(resp['msg'])
except ThirdPartyAPIError as api_err:
print(f'支付失败: {api_err}') # 业务逻辑错误
except ConnectionResetError:
print('支付网关连接中断') # 网络层错误
六、系统资源异常
解决思路:
- 尝试写入大文件到磁盘。
- 捕获
IOError
异常,处理IO错误(如磁盘空间不足)。 - 捕获
MemoryError
异常,处理内存不足的情况。 - 使用
finally
块确保文件资源被正确关闭。
命令部署:
try:
with open('large_file.txt', 'w') as f:
f.write('A' * 0**8)
except IOError as io_err:
print(f'IO错误: {io_err.errno}') # ENOSPC错误码处理
except MemoryError:
print('内存不足') # 缓冲区溢出
finally:
# 注意:由于使用了with语句,这里的finally块实际上是不必要的,因为with语句会自动关闭文件。
# 但为了保持格式一致,这里仍然保留finally块(虽然它是空的)。
pass # 或者直接省略finally块
(注意:实际上,在使用with
语句时,文件会在块结束时自动关闭,因此finally
块中的f.close()
是不必要的。这里保留finally
块仅为了格式上的统一,但通常可以省略。)
全局异常拦截方案
解决思路:
- 在Flask应用中定义全局异常处理器。
- 捕获内部服务器错误,返回JSON格式的错误响应,并包含请求ID(假设请求ID已通过
X-Request-ID
头传递)。
命令部署:
from flask import Flask, jsonify, request
app = Flask(__name__)
@app.errorhandler(0)
def handle_exception(e):
return jsonify({
'error': str(e),
'trace_id': request.headers.get('X-Request-ID')
}),