python蓝图、拦截器、异常处理、redis队列、线程池、控制台及日志文件输出

python蓝图、python拦截器、python统一异常处理、redis阻塞队列及redis连接池、线程池案例、控制台&日志文件输出

python 复制代码
from flask import Flask, request, jsonify
from pythonFlask.views.account import ac
from pythonFlask.views.order import order
import sys
import threading
import logging
import time
import redis
from redis.connection import ConnectionPool
import uuid
from concurrent.futures import ThreadPoolExecutor

REDIS_CONFIG = {
    "max_connections": 20,  # 连接池最大连接数
    "host": "XXXXXXX",
    "port": 6379,
    "db": 1,
    "password": "XXXXXX",  # 有密码填字符串,无则None
    "decode_responses": True,  # 自动bytes转str,不用手动decode
    "socket_timeout": None,  # 连接超时
    "retry_on_timeout": True,
    "socket_keepalive": True
}

# redis客户端
redisClient = redis.Redis(connection_pool=ConnectionPool(**REDIS_CONFIG))

# 日志
logging.basicConfig(filename="info.log", level=logging.INFO, encoding="UTF-8", filemode="w")
# 新增控制台输出
console = logging.StreamHandler(sys.stdout)
console.setLevel(logging.INFO)
logging.getLogger().addHandler(console)

TASK_QUEUE_NAME = "task_queue"


# @app.before_request  或者 app.before_request(auth)
def auth():
    logging.info(f"url:{request.path}")
    token = request.headers.get("token")
    print(request.path)
    print("读取token:", token)
    print("读取环境:", request.headers,
          type(request.headers))  # <class 'werkzeug.datastructures.headers.EnvironHeaders'>

    if request.method == "OPTIONS":  #
        return  # return代表方法结束,不拦截

    if request.path.startswith("/api/user/login"):
        return  # return代表方法结束,不拦截

    if not token:
        # 如何拦截?直接抛异常
        raise Exception("need login first")  # 抛出异常中断程序


###############################主应用开始########################################
app = Flask(__name__)


@app.errorhandler(500)
def internal_error(error):
    exc_type, exc_value, exc_traceback = sys.exc_info()
    # 安全获取异常信息
    if exc_value.args:
        message = str(exc_value.args[0])
    else:
        message = "服务器内部错误,请联系管理员"
    error_dict = {
        'success': False,
        'message': message,
        'data': None
    }
    logging.error(f"error:{error}")
    logging.error(f"error_message::{message}")
    return jsonify(error_dict), 500  # 如果你只返回 json、状态码依旧是 200。这里多返回一个500客户端本次请求结果:服务器内部错误


# 注册蓝图
app.register_blueprint(ac, url_prefix="/api/user")
app.register_blueprint(order, url_prefix="/api/order")
# 注册拦截器
app.before_request(auth)  # 这行代码等价@app.before_request


# 注册统一错误 处理
# app.errorhandle
# r(500)(internal_error) 已通过@app.errorhandler(500)包装
###############################主应用结束########################################


def publish(name):
    logging.info(name)
    flag = True
    while True:
        if flag:
            # 初始化塞入10条数据
            logging.info("一次性塞入10条订单")
            for x in range(10):
                redisClient.lpush(TASK_QUEUE_NAME, str(uuid.uuid4()))
            flag = False
        time.sleep(2)
        # 每2秒往redis队列塞一条
        new_order = str(uuid.uuid4())
        logging.info(f"【{threading.currentThread().getName()}】,生成新订单:{new_order}")
        redisClient.lpush(TASK_QUEUE_NAME, new_order)

def task_execute_function(name, task_uid):
    logging.info(f"【线程:{threading.currentThread().getName()}】,{name}开始处理订单:{task_uid}")
    # 在这里写真实订单业务逻辑
    time.sleep(3)
    logging.info(f"【线程:{threading.currentThread().getName()}】,{name}完成处理订单:{task_uid}")

def worker(name):
    # ✅ 线程池只创建一次!放到循环外面
    # 线程池
    # from concurrent.futures import ThreadPoolExecutor
    thread_pool = ThreadPoolExecutor(max_workers=10, thread_name_prefix="order_thread")
    try:
        while True:
            #queuename, task_str
            _, task_uuid_str = redisClient.brpop([TASK_QUEUE_NAME])
            # 提交任务到线程池并发执行
            thread_pool.submit(task_execute_function, name, task_uuid_str)
    finally:
        # 程序退出时优雅关闭线程池
        #wait = Ture:当前调用 shutdown 的线程阻塞等待,线程池中已经提交、正在运行的任务全部执行完毕
        thread_pool.shutdown(wait=True)

if __name__ == '__main__':
    # 启动一个守护线程,不断的读取队列
    threading.Thread(target=publish, args=("订单队列启动!",), daemon=True).start()
    threading.Thread(target=worker, args=("订单处理者",), daemon=True).start()
    redisClient.delete(TASK_QUEUE_NAME)
    app.run()
python 复制代码
#包pythonFlask.views.account.py
from flask import Blueprint
ac = Blueprint("account",__name__)
@ac.route("/login", methods=["get","POST"])
def login():
    return "登录"


#包pythonFlask.views.order.py
from flask import Blueprint
order = Blueprint("order",__name__)
@order.route("/order_list")
def order_list():
    return "订单列表"
相关推荐
科技研学社几秒前
服装厂激光开袋机与智能模板机怎么选?核心工序设备深度对比与落地实战
数据库·python
张张123y4 小时前
后端第十四课:Agent 记忆系统(让 Agent 记住上下文和用户,跨会话不健忘)
java·大数据·人工智能·python·agent·记忆
happylifetree9 小时前
Python67:核心语法-函数进阶-参数类型(函数作为参数)
python
小羊没烦恼!9 小时前
铁道部新客票系统设计(二)
开发语言·前端·数据库·python·oracle·c#·php
quantdash_cc10 小时前
从实时行情到价格观察表:用 Python 和 Pandas 构建策略输入数据
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
镜子AI10 小时前
镜子AI工程实践:用 Python 做 GEO 实体一致性审计,并自动生成 JSON-LD 结构化数据
人工智能·python·json
2601_9628857214 小时前
如何用 Python 计算 VaR 和 CVaR(在险价值)?
开发语言·python
李航198314 小时前
DeepSeekAI建模三 - 实战建模一组柜子
人工智能·python·计算机视觉·ai·ai编程
严谨的麻辣烫16 小时前
静态代理 IP 的出口一致性如何验证?Python 请求检测与异常排查
开发语言·python·http·网络安全
我命由我1234516 小时前
5-1.Python 编码进阶 - 函数进阶(参数、返回值、递归、函数作为参数传递、lambda 匿名函数)
java·服务器·数据库·后端·python·java-ee·python3.11