Python 权限装饰器与日志模块:给函数穿防护马甲 + 让程序写日记

📅 2026/7/31 5:58:40 👁️ 阅读次数 📝 编程学习
Python 权限装饰器与日志模块:给函数穿防护马甲 + 让程序写日记

文章目录

📖 前言

第一部分:权限装饰器 —— 给函数“穿防护马甲”

1.1 权限装饰器 —— 未登录有效保护

1.2 怎么调用装饰器?

1.3 @wraps(func) 是干嘛的?

1.4 装饰器核心总结

第二部分:logging 日志模块 —— 让程序学会“写日记”

2.1 为什么要用日志?

2.2 日志的五个级别(从低到高)

2.3 基础用法 —— 按你图中的代码来

2.4 图解:日志是怎么流动的

2.5 多个日志实例(独立模块)

2.6 日志格式占位符说明

2.7 日志模块核心总结

🧁 结尾


📖 前言

在 Python 编程中,我们常常会遇到一些看似简单却非常实用的技巧,它们能极大提升代码的可维护性和安全性。今天不讲复杂的概念,就聊两件特别实用的事:

第一件:权限装饰器—— 这是一种优雅的设计模式,它允许你在不改变函数本身代码的情况下,为函数“穿上防护马甲”,添加额外的功能。想象一下,你有一个需要登录才能访问的个人中心页面,传统做法是在每个函数开头都加上登录检查的代码,这样不仅重复,还容易出错。而装饰器可以让你用一行@login_required就搞定所有需要权限验证的函数,代码简洁又安全。

第二件:日志模块—— 这是程序“写日记”的能力。在开发阶段,我们习惯用print()来调试,但当程序部署到服务器上后,你不可能一直盯着屏幕看输出。日志模块让程序能够自动把运行过程中的关键信息(如错误、警告、用户操作等)记录到文件中。当程序出现问题时,你可以像查案一样翻阅日志文件,快速定位问题根源,这比靠眼睛盯着屏幕找错误靠谱一万倍。

这两件事虽然基础,但却是 Python 开发中不可或缺的实用技能。本文将按照清晰的思路,分开讲解这两个主题,每个部分都配有详细的代码示例和流程图,确保你不仅能理解原理,还能立即上手应用到自己的项目中。让我们开始吧!🚀

第一部分:权限装饰器 —— 给函数“穿防护马甲”


1.1 权限装饰器 —— 未登录有效保护

python

from functools import wraps user = None # 全局变量,记录当前登录用户,默认没人 def login_required(func): @wraps(func) # 保留原函数的名字和注释(方便调试) def check_login(): """check_login 注释说明""" global user if user: # 已经登录了 → 直接执行原函数 func() else: # 没登录 → 让用户输入账号密码 user_name = input("输入用户名:") password = input("输入密码:") if user_name == "admin" and password == "123456": user = user_name func() else: print("用户名或者密码错误") return check_login

这段代码的执行逻辑:

text

调用被装饰的函数 ↓ 检查 user 是否为空 ↓ ┌────┴────┐ ↓ ↓ user 有值 user 是 None (已登录) (未登录) ↓ ↓ 直接执行 让你输账号密码 原函数 ↓ ┌───┴───┐ ↓ ↓ 正确 错误 ↓ ↓ 登录成功 提示错误 ↓ 执行原函数

1.2 怎么调用装饰器?

python

# 普通函数:不用登录就能看 def index(): print("欢迎来到首页") 加了 @login_required 的函数:必须先登录才能进 @login_required def center(): """center 是个人中心""" print("欢迎来到个人中心") @login_required def wallet(): print("欢迎来到钱包页面") 调用 index() # 直接输出:欢迎来到首页 center() # 没登录的话会让你输账号密码 wallet() # 登录过一次之后,后面的函数直接放行

运行效果:

第一次调用center()

text

输入用户名:admin 输入密码:123456 欢迎来到个人中心

第二次调用wallet()(已登录,不用再输):

text

欢迎来到钱包页面

1.3@wraps(func)是干嘛的?

不加@wraps(func),你的函数名字会被“偷换”掉:

python

# 不加 @wraps def login_required(func): def check_login(): pass return check_login @login_required def center(): """我是个人中心""" pass print(center.name) # check_login ← 函数名变了!

加了@wraps(func)之后:

python

from functools import wraps def login_required(func): @wraps(func) def check_login(): pass return check_login @login_required def center(): """我是个人中心""" pass print(center.name) # center ← 还是原来的名字

📌 一句话:@wraps的作用就是“把原函数的身份信息(名字、注释等)复制给包装函数”,方便调试和查错。

1.4 装饰器核心总结

概念说明
本质闭包 + 语法糖
作用不改变原函数,给函数加新功能
@wraps保住原函数的名字和注释
global user在函数里修改全局变量
@login_required执行函数前先校验是否登录

第二部分:logging日志模块 —— 让程序学会“写日记”

2.1 为什么要用日志?

写代码的时候,你习惯用print()来调试。但程序跑在服务器上之后,你不可能一直盯着屏幕看。这时候就需要日志——程序自己把运行信息写进文件里,出问题了你去翻文件就能查到。

日志的作用:

场景说明
排查错误程序崩了,翻日志看哪里出了问题
监控运行看程序在什么时间干了什么事
记录关键操作谁在什么时候删了什么数据

2.2 日志的五个级别(从低到高)

级别函数啥时候用
DEBUGlogger.debug()调试信息,最详细
INFOlogger.info()常规运行信息
WARNINGlogger.warning()警告,不影响运行
ERRORlogger.error()出错了,但程序还能跑
CRITICALlogger.critical()严重错误,程序要挂了

📌级别规则:设置了setLevel(logging.WARNING),就只会记录WARNING及以上级别(WARNING、ERROR、CRITICAL),DEBUGINFO就不显示了。

2.3 基础用法 —— 按你图中的代码来

python

import logging 1. 创建日志实例 logger = logging.getLogger(name) # name 是当前模块名 logger.setLevel(logging.DEBUG) # 设置级别,覆盖默认的 WARNING 2. 创建控制台处理器(输出到屏幕) stream_handler = logging.StreamHandler() stream_handler.setLevel(logging.INFO) # 控制台只显示 INFO 及以上 设置控制台输出格式 stream_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') stream_handler.setFormatter(stream_formatter) 把处理器添加到日志实例 logger.addHandler(stream_handler) 3. 创建文件处理器(输出到文件) file_handler = logging.FileHandler('log.txt') file_handler.setLevel(logging.WARNING) # 文件只记录 WARNING 及以上 设置文件输出格式 file_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') file_handler.setFormatter(file_formatter) 把处理器添加到日志实例 logger.addHandler(file_handler) 4. 输出日志 logger.debug("debug 信息") # 只有控制台显示(因为控制台是 INFO,会显示 DEBUG 及以上) logger.info("info 信息") # 控制台显示(INFO 及以上),文件不显示(WARNING 以下不记录) logger.warning("warning 信息") # 控制台 + 文件都显示 logger.error("error 信息") # 控制台 + 文件都显示 logger.critical("critical 信息")# 控制台 + 文件都显示

2.4 图解:日志是怎么流动的

text

logger.setLevel(DEBUG) ↓ 日志实例(总开关:DEBUG) ↓ ┌────┴────┐ ↓ ↓ 控制台处理器 文件处理器 setLevel(INFO) setLevel(WARNING) ↓ ↓ 显示 INFO及以上 显示 WARNING及以上 ↓ ↓ 屏幕 log.txt

📌一句话:总开关决定哪些日志能进系统,各个处理器再根据自己的级别决定哪些显示到屏幕、哪些写到文件。

2.5 多个日志实例(独立模块)

不同模块可以用各自的日志实例,互不干扰:

python

# 在另一个文件或另一个模块里 logger2 = logging.getLogger("用户模块") logger2.setLevel(logging.DEBUG) file_handler = logging.FileHandler('log2.txt', encoding='utf-8') file_handler.setLevel(logging.WARNING) file_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') file_handler.setFormatter(file_formatter) logger2.addHandler(file_handler) logger2.info("用户登录了") # 只显示在屏幕 logger2.warning("用户多次输错密码") # 显示在屏幕 + 写入 log2.txt

💡logging.getLogger("用户模块")里的名字会出现在日志中,方便你区分是哪块代码打的日志。

2.6 日志格式占位符说明

占位符含义示例
%(asctime)s时间2026-07-30 14:30:25
%(name)s日志实例名称__main__用户模块
%(levelname)s日志级别INFOWARNING
%(message)s日志内容你写的具体信息
%(filename)s文件名demo.py
%(lineno)d行号10

2.7 日志模块核心总结

组件作用
getLogger(name)创建日志实例
setLevel()设置总级别
StreamHandler()输出到控制台(屏幕)
FileHandler()输出到文件
Formatter()设置日志格式
logger.debug/info/warning/error/critical()输出不同级别的日志

🎯 今天知识点速查

装饰器部分

概念说明
@login_required加登录校验装饰器
@wraps(func)保住原函数名字
global user修改全局变量
本质闭包 + 语法糖

日志部分

级别函数用途
DEBUGlogger.debug()调试信息
INFOlogger.info()常规信息
WARNINGlogger.warning()警告
ERRORlogger.error()错误
CRITICALlogger.critical()严重错误

🧁 结尾

今天两件事都不难,但特别实用

权限装饰器能为你的网页在未登录时提供有效保护,避免非法访问和攻击。

日志模块让你程序学会写日记,出了错翻文件查,不用靠print()一条条盯着屏幕看。

两个工具让你的码农之路又获得一些技能吧,各位糕手

下期我们聊点啥呢?保持期待吧~ 咱们下期见!👋🐍