先看一个最基础的API接口长什么样。但注意,这里有个常见的坑:很多人启动项目后直接在代码里写 app.run(host='0.0.0.0'),这在生产环境就是灾难。
“python
正确的API入口文件 - app.py
from flask import Flask, jsonify, request
from flask_cors import CORS
import logging
app = Flask(__name__)
CORS(app) # 处理跨域,不然后端会莫名其妙报错
配置日志 - 这个很多人会忽略,出了问题全靠猜
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
@app.route('/api/v1/health', methods=['GET'])
def health_check():
"""健康检查接口,部署后一定要有"""
return jsonify({
'status': 'ok',
'version': '1.0.0',
'message': '服务运行正常'
})
@app.route('/api/v1/users', methods=['GET'])
def get_users():
"""获取用户列表 - 注意分页"""
page = request.args.get('page', 1, type=int)
per_page = request.args.get('per_page', 10, type=int)
# 这里加个参数校验,不然用户传负数就炸了
if page < 1 or per_page < 1 or per_page > 100:
return jsonify({'error': '参数错误'}), 400
# 模拟数据库查询(实际用ORM代替)
users = [
{'id': 1, 'name': '张三', 'email': 'zhangsan@example.com'},
{'id': 2, 'name': '李四', 'email': 'lisi@example.com'}
]
return jsonify({
'data': users,
'total': len(users),
'page': page,
'per_page': per_page
})
`
这里应该放一张API接口的思维导图,展示从请求到响应的完整流程,包括中间件、认证、限流等环节。
这个设计真的反人类:Flask默认是单线程的,一个请求处理慢一点,其他请求全堵住。我第一次上线就发现,并发一上来,响应时间从20ms飙到5秒,服务直接挂了。
另一个坑:错误处理。99%的教程都不教这个,但生产环境没有错误处理就是等死。
`python
统一错误处理 - 这个必须加
@app.errorhandler(404)
def not_found(error):
return jsonify({
'error': '资源不存在',
'code': 404,
'message': str(error)
}), 404
@app.errorhandler(500)
def internal_error(error):
# 记得记录日志,不然出问题你都不知道为什么
logger.error(f'服务器内部错误: {str(error)}')
return jsonify({
'error': '服务器内部错误',
'code': 500,
'message': '请稍后重试'
}), 500
装饰器自动捕获异常 - 这个黑科技绝了
from functools import wraps
def handle_exceptions(f):
@wraps(f)
def wrapper(*args, **kwargs):
try:
return f(*args, **kwargs)
except ValueError as e:
return jsonify({'error': str(e), 'code': 400}), 400
except PermissionError as e:
return jsonify({'error': str(e), 'code': 403}), 403
except Exception as e:
logger.exception(f'未预期的错误: {str(e)}')
return jsonify({'error': '服务器内部错误', 'code': 500}), 500
return wrapper
使用示例
@app.route('/api/v1/user/
@handle_exceptions
def get_user(user_id):
if user_id <= 0:
raise ValueError('用户ID必须为正数')
# ... 处理逻辑
return jsonify({'id': user_id, 'name': '测试用户'})
`
看到没?用装饰器把异常处理统一管理,代码瞬间清爽了。以前我每个接口都写try-except,代码像裹脚布一样又臭又长。
还有个技巧:API版本控制。别问我为什么知道,经历过一次接口升级导致所有客户端崩溃的人都会把这个当圣经。
`python
API版本控制方案 - 通过URL路径
版本1:/api/v1/...
版本2:/api/v2/...
创建蓝图实现版本隔离
from flask import Blueprint
v1 = Blueprint('v1', __name__)
v2 = Blueprint('v2', __name__)
@v1.route('/users', methods=['GET'])
def get_users_v1():
"""v1版本返回旧格式"""
return jsonify([{'id': 1, 'name': '张三'}])
@v2.route('/users', methods=['GET'])
def get_users_v2():
"""v2版本返回新格式,包含更多字段"""
return jsonify({
'total': 1,
'items': [{'id': 1, 'name': '张三', 'created_at': '2024-01-01'}]
})
注册蓝图
app.register_blueprint(v1, url_prefix='/api/v1')
app.register_blueprint(v2, url_prefix='/api/v2')
`
说到这里,官方文档这段文档不够清晰,关于Blueprint的url_prefix和子路由的嵌套规则,我调试了整整三小时才发现是斜杠的问题。记住:父级带斜杠,子级就不带,反之亦然。
这里建议放一张API性能优化前后的对比图表,展示从优化前200ms到优化后20ms的具体数据。
性能优化这块,我踩的坑最多。一个简单的查询接口,从数据库里取1000条数据,直接返回JSON,第一次测试耗时3.2秒。优化后降到0.8秒,分享一下我是怎么做的:
`python
性能优化后的API - 带缓存
import ujson
from redis import Redis
from functools import wraps
redis_client = Redis(host='localhost', port=6379, db=0)
def cache_response(timeout=300):
"""缓存装饰器 - 减少数据库压力"""
def decorator(f):
@wraps(f)
def wrapper(*args, **kwargs):
# 生成缓存键
cache_key = f"api:{f.__name__}:{str(kwargs)}"
# 尝试从缓存获取
cached = redis_client.get(cache_key)
if cached:
return ujson.loads(cached)
# 执行原函数
result = f(*args, **kwargs)
# 存入缓存
redis_client.setex(cache_key, timeout, ujson.dumps(result))
return result
return wrapper
return decorator
@app.route('/api/v1/users/optimized', methods=['GET'])
@cache_response(timeout=60)
def get_users_optimized():
"""优化后的用户列表接口"""
# 使用原生SQL比ORM快30%-50%
# 这里用参数化查询防止SQL注入
cursor = db_connection.cursor()
cursor.execute("SELECT id, name, email FROM users WHERE status = 'active' LIMIT 100")
users = cursor.fetchall()
# 用列表推导式代替循环,快2倍
result = [
{'id': u[0], 'name': u[1], 'email': u[2]}
for u in users
]
return {
'data': result,
'count': len(result),
'cached': False
}
``
最后说一下部署。很多人以为写完了代码就算完了,结果服务器一跑就炸。我的生产部署方案:
- 用Gunicorn替代Flask内置服务器,配置4个worker进程
- 前面挂Nginx做负载均衡和静态文件处理
- 用supervisor管理进程,崩溃后自动重启
- 配置Prometheus + Grafana监控,接口响应时间、错误率一目了然
这里放一张完整的部署架构图,展示Nginx、Gunicorn、Flask、Redis、数据库的交互关系。
总结一下,你可以立刻用的三个点:
记住,写API不是为了炫技,是为了让前端开发、移动端开发能开心地调用。多用JSON格式,文档写清楚,参数有校验,出了问题有日志,这就是一个好API的标准。