【Python 进阶:权限校验装饰器与 logging 日志系统,12 大实战技巧一篇搞定!】
Python 进阶权限校验装饰器与 logging 日志系统12 大实战技巧一篇搞定摘要还在用 print 调试代码权限校验逻辑散落在每个函数里本文从装饰器闭包原理讲起手写一套生产级权限校验装饰器无参/有参/类装饰器三种形态再深入 Python logging 四大组件涵盖日志分级、多 Handler 输出、文件轮转和装饰器 logging 联动实战。全程代码可独立运行读完就能落地到自己的项目里。从手写装饰器到搭建可落地的日志系统12 个实战案例覆盖权限校验和 logging 全链路代码全部可复制运行Python 项目越写越大之后两个问题会反复出现一是每个敏感函数里都塞了一段if user.role ! admin: raise…代码又臭又长二是到处 print 调试信息上线后要么删不干净要么根本看不到日志。装饰器和 logging 就是为这两个问题而生的——一个把权限校验逻辑抽离复用一个把日志管理变得可控、可配置。一、装饰器基础回顾在写权限校验装饰器之前先把装饰器的工作原理吃透。不然后面带参装饰器、类装饰器会一头雾水。1.1 函数是一等公民Python 里函数就是对象可以赋值给变量、作为参数传递、在另一个函数里定义defgreet(name):returnfHello,{name}!# 函数可以赋值给变量saygreetprint(say(World))# Hello, World!# 函数可以作为参数传递defrun(func,arg):returnfunc(arg)print(run(greet,Python))# Hello, Python!1.2 最简单的装饰器装饰器本质上是一个接受函数、返回新函数的高阶函数importfunctoolsimporttimedeftimer(func):统计函数执行时间的装饰器functools.wraps(func)# 保留原函数的 __name__ 和 __doc__defwrapper(*args,**kwargs):starttime.perf_counter()resultfunc(*args,**kwargs)elapsedtime.perf_counter()-startprint(f[timer]{func.__name__}耗时:{elapsed:.4f}s)returnresultreturnwrappertimerdefcompute(n):total0foriinrange(n):totali**2returntotalprint(compute(1000000))# [timer] compute 耗时: 0.0521s# 333332833333500000要点说明timer语法糖等价于compute timer(compute)functools.wraps必须加否则compute.__name__会变成wrapper*args, **kwargs保证装饰器适配任意参数签名一句话decorator就是func decorator(func)装饰器必须返回一个 callable。二、权限校验装饰器实战2.1 场景设定以下代码假设有一个全局变量current_user代表当前登录用户生产环境中可替换为 Flask 的g.user、Django 的request.user或从 session/token 中读取# 模拟用户数据classUser:def__init__(self,id,name,role):self.ididself.namename self.rolerole# admin | editor | viewercurrent_userUser(1,张三,viewer)2.2 无参装饰器单一角色校验最简单的场景——只允许 admin 调用importfunctoolsdefrequire_admin(func):只允许 admin 角色调用 —— 无参装饰器functools.wraps(func)defwrapper(*args,**kwargs):ifcurrent_user.role!admin:raisePermissionError(f用户{current_user.name}(角色:{current_user.role}) 无权限执行{func.__name__})returnfunc(*args,**kwargs)returnwrapperrequire_admindefdelete_user(user_id):删除用户 —— 仅 admin 可调用returnf用户{user_id}已删除# 测试viewer 调用 admin 接口try:print(delete_user(42))exceptPermissionErrorase:print(e)# 用户 张三 (角色: viewer) 无权限执行 delete_user2.3 带参装饰器多角色/多权限等级需要支持允许 admin 或 editor 调用就得让装饰器接收参数importfunctoolsdefrequire_role(*allowed_roles):# 外层接收装饰器参数允许指定角色列表调用 —— 带参装饰器defdecorator(func):# 中层接收被装饰函数functools.wraps(func)# 内层 wrapper 替换原函数defwrapper(*args,**kwargs):ifcurrent_user.rolenotinallowed_roles:raisePermissionError(f用户{current_user.name}(角色:{current_user.role}) f不属于{allowed_roles}无权执行{func.__name__})returnfunc(*args,**kwargs)returnwrapperreturndecoratorrequire_role(admin,editor)defedit_article(article_id,content):编辑文章 —— admin 或 editor 可调用returnf文章{article_id}已更新为:{content}require_role(admin)defgrant_role(user_id,new_role):授权操作 —— 仅 adminreturnf用户{user_id}角色变更为{new_role}# 测试print(edit_article(1,新内容))# 触发 PermissionError (viewer 无权)三层嵌套原理层接收的参数返回第 1 层require_role*allowed_roles装饰器参数decorator函数第 2 层decoratorfunc被装饰函数wrapper函数第 3 层wrapper*args, **kwargs原函数参数原函数的返回值记住规律每多一层嵌套就多一个可配置维度。带参装饰器 无参装饰器外面再套一层。2.4 类装饰器权限校验 审计日志类装饰器比函数装饰器更适合有状态的场景——比如记录每个接口的调用次数importfunctoolsfromcollectionsimportdefaultdictclassrequire_permission:类装饰器权限校验 调用统计call_countdefaultdict(int)# 类级别统计def__init__(self,*roles):self.allowed_rolesrolesdef__call__(self,func):functools.wraps(func)defwrapper(*args,**kwargs):ifcurrent_user.rolenotinself.allowed_roles:raisePermissionError(f{current_user.name}无权访问{func.__name__})require_permission.call_count[func.__name__]1resultfunc(*args,**kwargs)print(f[AUDIT]{current_user.name}调用了{func.__name__}f(第{require_permission.call_count[func.__name__]}次))returnresultreturnwrapperrequire_permission(admin,editor)defpublish_post(post_id):returnf文章{post_id}已发布# 模拟切换用户测试current_userUser(2,李四,admin)print(publish_post(101))# [AUDIT] 李四 调用了 publish_post (第 1 次)# 文章 101 已发布print(publish_post(102))# [AUDIT] 李四 调用了 publish_post (第 2 次)# 文章 102 已发布三种装饰器对比类型写法适用场景无参函数装饰器require_admin单一校验逻辑固定带参函数装饰器require_role(admin)需要配置参数角色列表等类装饰器require_permission(admin)需要维护状态统计、缓存等三、logging 日志系统基础权限校验只告诉你谁不可以做什么真正排查问题还得靠日志。Python 内置的 logging 模块足够强大不需要装第三方库。3.1 为什么不用 printprintlogging输出到 stdout改不了目标可同时输出到文件、控制台、远程服务器只有一种级别全输出5 个级别DEBUG / INFO / WARNING / ERROR / CRITICAL上线后要删干净配置即可关闭 DEBUG 级别保留 ERROR没有时间戳、调用位置自动记录时间、文件名、行号、进程 ID无性能控制可异步写入、批量刷新3.2 logging 四大组件importlogging# 1. Logger — 日志记录器入口loggerlogging.getLogger(my_app)logger.setLevel(logging.DEBUG)# 设置最低记录级别# 2. Handler — 处理器输出目标console_handlerlogging.StreamHandler()# 输出到控制台console_handler.setLevel(logging.INFO)# 控制台只看 INFO 以上file_handlerlogging.FileHandler(app.log,encodingutf-8)file_handler.setLevel(logging.DEBUG)# 文件记录所有级别# 3. Formatter — 格式化器输出格式formatterlogging.Formatter(fmt%(asctime)s | %(levelname)-8s | %(name)s | %(funcName)s:%(lineno)d | %(message)s,datefmt%Y-%m-%d %H:%M:%S)console_handler.setFormatter(formatter)file_handler.setFormatter(formatter)# 4. Filter — 过滤器可选按条件过滤日志# 此处省略一般用 Handler 级别控制即可# 组装logger.addHandler(console_handler)logger.addHandler(file_handler)# 测试logger.debug(变量 x %d,42)# 仅写入文件logger.info(服务启动成功)# 控制台 文件logger.warning(内存使用率 85%%)# 控制台 文件logger.error(数据库连接失败,exc_infoTrue)# exc_infoTrue 附带堆栈运行后控制台输出2026-07-30 18:05:12 | INFO | my_app | module:30 | 服务启动成功 2026-07-30 18:05:12 | WARNING | my_app | module:31 | 内存使用率 85% 2026-07-30 18:05:12 | ERROR | my_app | module:32 | 数据库连接失败而app.log文件里还会多一行DEBUG日志。3.3 日志级别与使用场景级别数值使用场景DEBUG10开发调试变量值、函数入参出参INFO20关键业务流程节点用户登录、订单创建WARNING30非预期但可恢复内存告警、重试成功ERROR40需要人工介入接口调用失败、数据异常CRITICAL50系统级故障数据库宕机、磁盘满生产环境推荐 INFO 级别排查线上问题时临时降到 DEBUG。3.4 日志文件轮转RotatingFileHandler日志文件会无限增长必须做轮转fromlogging.handlersimportRotatingFileHandler# 单个文件最大 5MB保留 3 个备份app.log, app.log.1, app.log.2, app.log.3rotating_handlerRotatingFileHandler(app.log,maxBytes5*1024*1024,backupCount3,encodingutf-8)rotating_handler.setFormatter(formatter)logger.addHandler(rotating_handler)或者按时间切分每天一个新文件fromlogging.handlersimportTimedRotatingFileHandler# 每天凌晨切分保留 7 天timed_handlerTimedRotatingFileHandler(app.log,whenmidnight,interval1,backupCount7,encodingutf-8)timed_handler.setFormatter(formatter)logger.addHandler(timed_handler)3.5 装饰器 logging 联动自动记录函数调用把前面两套知识合在一起写一个实用的函数调用日志装饰器importloggingimporttimeimportfunctools logging.basicConfig(levellogging.INFO,format%(asctime)s | %(levelname)-8s | %(message)s,datefmt%H:%M:%S)loggerlogging.getLogger(audit)deflog_call(func):自动记录函数调用入参、出参、耗时、异常functools.wraps(func)defwrapper(*args,**kwargs):# 裁剪长参数避免日志爆炸args_repr[repr(a)[:50]forainargs]kwargs_repr{k:repr(v)[:50]fork,vinkwargs.items()}signaturef{func.__name__}({, .join(args_repr)},{kwargs_repr}).strip(, {})logger.info( 调用 %s,signature)starttime.perf_counter()try:resultfunc(*args,**kwargs)elapsedtime.perf_counter()-start result_reprrepr(result)[:80]logger.info( %s 完成 (%.4fs) - %s,func.__name__,elapsed,result_repr)returnresultexceptExceptionase:elapsedtime.perf_counter()-start logger.error(!!! %s 异常 (%.4fs): %s,func.__name__,elapsed,e,exc_infoTrue)raisereturnwrapper# ---- 与权限装饰器叠加使用 ----log_callrequire_role(admin,editor)deftransfer_money(from_user,to_user,amount):转账 —— 需要权限 记录日志returnf{amount}元从{from_user}转到{to_user}# 切换为 admincurrent_userUser(3,王五,admin)print(transfer_money(王五,赵六,1000))输出18:10:33 | INFO | 调用 transfer_money(王五, 赵六, 1000) 18:10:33 | INFO | transfer_money 完成 (0.0001s) - 1000 元从 王五 转到 赵六 1000 元从 王五 转到 赵六3.6 生产级 logging 配置模板不用代码拼接直接用logging.config.dictConfig集中管理importlogging.config LOGGING_CONFIG{version:1,disable_existing_loggers:False,formatters:{default:{format:%(asctime)s | %(levelname)-8s | %(name)s | %(message)s,datefmt:%Y-%m-%d %H:%M:%S,},detailed:{format:%(asctime)s | %(levelname)-8s | %(name)s | %(pathname)s:%(lineno)d | %(funcName)s | %(message)s,},},handlers:{console:{class:logging.StreamHandler,level:INFO,formatter:default,},file:{class:logging.handlers.RotatingFileHandler,level:DEBUG,formatter:detailed,filename:app.log,maxBytes:5*1024*1024,# 5MBbackupCount:5,encoding:utf-8,},error_file:{class:logging.FileHandler,level:ERROR,formatter:detailed,filename:error.log,encoding:utf-8,},},root:{# 根 Logger 配置level:DEBUG,handlers:[console,file,error_file],},}logging.config.dictConfig(LOGGING_CONFIG)loggerlogging.getLogger(__name__)logger.info(应用启动 -- 日志系统已初始化)logger.debug(数据库连接池大小: 20)logger.error(支付回调验签失败: order_id12345)运行后生成 3 条输出路径控制台INFO 及以上app.log全部级别自动轮转error.log仅 ERROR 和 CRITICAL方便告警监控直接 tail四、总结速查表4.1 装饰器速查需求写法关键点单一角色校验require_admin一层嵌套函数返回函数多角色校验require_role(admin, editor)三层嵌套外层收参数需要维护状态class require_permission__init__收参数__call__实现逻辑保留原函数元信息functools.wraps(func)写在 wrapper 上一行多个装饰器叠加log_call在上require_role在下执行顺序从下往上越靠近函数定义的越先执行4.2 logging 速查需求方法创建 Loggerlogging.getLogger(name)设置级别logger.setLevel(logging.DEBUG)输出到控制台logging.StreamHandler()输出到文件logging.FileHandler(app.log)按大小轮转RotatingFileHandler(maxBytes5MB, backupCount3)按时间轮转TimedRotatingFileHandler(whenmidnight)自定义格式logging.Formatter(fmt..., datefmt...)字典配置logging.config.dictConfig(CONFIG_DICT)记录异常logger.error(msg, exc_infoTrue)别用 root logger始终用getLogger(__name__)避免第三方库日志污染如果这篇文章帮你搞懂了装饰器和 logging欢迎点赞收藏。有疑问欢迎在评论区留言讨论

相关新闻

神经网络基础与实战:从原理到MNIST分类实现

神经网络基础与实战:从原理到MNIST分类实现

1. 神经网络基础:从生物神经元到数学模型 神经网络的核心思想源自对人类大脑神经元工作方式的模拟。生物神经元通过树突接收信号,当信号强度超过阈值时,轴突会触发电脉冲传递信息。在人工神经网络中,我们用数学函数来模拟这一过程…

2026/7/31 6:18:00 阅读更多 →
高通9008模式救砖全攻略:从原理到实战,拯救变砖安卓设备

高通9008模式救砖全攻略:从原理到实战,拯救变砖安卓设备

1. 项目概述:当平板变成“砖头”,我们如何自救?手里拿着一台彻底黑屏、无法开机、连充电指示灯都不亮的联想小新Pad,那种感觉就像捧着一块昂贵的“电子砖头”。对于很多用户来说,这几乎是数码设备最绝望的状态。但作为…

2026/7/31 6:18:00 阅读更多 →
基于Pact的Spring Cloud微服务契约测试实践:从消费者驱动到自动化验证

基于Pact的Spring Cloud微服务契约测试实践:从消费者驱动到自动化验证

1. 项目概述:为什么微服务集成测试是个“老大难”?在微服务架构里摸爬滚打几年,最让人头疼的往往不是单个服务的开发,而是服务之间的集成。你这边改了个接口参数,那边调用方就挂了;他那边升级了个依赖版本&…

2026/7/31 6:18:00 阅读更多 →

最新新闻

CXMT市值突破4万亿:A股“半导体之王”加冕,存储芯片的黄金时代与冷思考

CXMT市值突破4万亿:A股“半导体之王”加冕,存储芯片的黄金时代与冷思考

摘要: 7月31日早盘,CXMT(长鑫存储)盘中市值历史性地突破4万亿元人民币大关,续写上市首周的神话。在国产替代浪潮与全球存储周期共振的背景下,这家科创板“巨无霸”正以惊人速度重塑A股估值体系。本文将从首…

2026/8/1 8:00:07 阅读更多 →
SpringBoot农产品预售平台开发实战与技术解析

SpringBoot农产品预售平台开发实战与技术解析

1. 项目概述:农产品预售平台的现实意义与技术选型去年帮学弟调试这个农产品预售平台时,我惊讶地发现后台订单里60%来自城市上班族——他们凌晨下单,备注栏写着"老家味道"。这个现象折射出当代社会的深层需求:城市化进程…

2026/8/1 8:00:07 阅读更多 →
GPT-5.6 全系来了!三档模型 ChatU 一站式接入,企业 AI 能力再升级!

GPT-5.6 全系来了!三档模型 ChatU 一站式接入,企业 AI 能力再升级!

就在7月9日OpenAI正式发布GPT-5.6系列模型,这一代的更新直接从单旗舰模型,走向了“Sol-Terra-Luna”三层能力矩阵。大模型正在从“用一个模型解决所有问题”,走向更加精细的任务分工:复杂任务调用高能力模型,日常任务使…

2026/8/1 8:00:07 阅读更多 →
GinCdn被控节点V1.0.7 安装教程(Ubuntu 18~24 通用,推荐 Ubuntu 24.04|2H2G~16H32G)

GinCdn被控节点V1.0.7 安装教程(Ubuntu 18~24 通用,推荐 Ubuntu 24.04|2H2G~16H32G)

GinCdn被控节点V1.0.7 安装教程(Ubuntu 18~24 通用,推荐 Ubuntu 24.04|2H2G~16H32G)前言GinCdn 是一款轻量、高性能、易部署的国产内容分发系统,采用主控边缘节点架构,支持缓存加速、HTTPS、智能调度、WAF …

2026/8/1 8:00:07 阅读更多 →
5分钟快速部署:大麦网自动抢票脚本终极指南,告别抢票焦虑

5分钟快速部署:大麦网自动抢票脚本终极指南,告别抢票焦虑

5分钟快速部署:大麦网自动抢票脚本终极指南,告别抢票焦虑 【免费下载链接】Automatic_ticket_purchase 大麦网抢票脚本 项目地址: https://gitcode.com/GitHub_Trending/au/Automatic_ticket_purchase 还在为抢不到心仪的演唱会门票而烦恼吗&…

2026/8/1 8:00:07 阅读更多 →
音频功放OTL、OCL、BTL三大架构核心原理与选型指南

音频功放OTL、OCL、BTL三大架构核心原理与选型指南

1. 项目概述:音频功率放大器的三种经典架构在音响发烧友的圈子里,或者在电子工程师的案头,当讨论到如何驱动一个喇叭发出响亮而纯净的声音时,OTL、OCL、BTL这三个缩写词几乎是绕不开的话题。它们代表了三种经典的音频功率放大器输…

2026/8/1 7:59:07 阅读更多 →

日新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/1 0:00:48 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/1 0:00:48 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/1 0:00:48 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/31 1:03:03 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/8/1 5:19:34 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/31 4:19:39 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/1 0:00:48 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/1 0:00:48 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/1 0:00:48 阅读更多 →