日志的轮转
按时间 日志文件名称接的是开始时间 TimedRotatingFileHandler
按大小 一般日志文件名称接的是大小 RotatingFileHandler
#按照大小轮转创建
#传入参数:名字 最大字节 备份数量
fh=RotatingFileHandler("sc-bak.log",maxBytes=100,backupCount=2)
#按时间轮转创建处理器
#传入参数:名字 时间单位 周期(这里表示2s轮转一次) 备份数量(保留几个历史轮转文件 2个)
fh=TimedRotatingFileHandler("sc.log",when="S",interval=2,backupCount=2)
Linux里面/etc/logrotate里rorate=4表示保留4个历史日志文件
搭建一个程序考虑的方面:日志 监控
#按时间轮转创建处理器
import logging
import time
from logging.handlers import TimedRotatingFileHandler,RotatingFileHandler
logger=logging.getLogger()
#按时间轮转创建处理器
#传入参数:名字 时间单位 周期(这里表示2s轮转一次) 备份数量(保留几个历史轮转文件 2个)
fh=TimedRotatingFileHandler("sc.log",when="S",interval=2,backupCount=2)
#按照大小轮转创建
#传入参数:名字 最大字节 备份数量
fh=RotatingFileHandler("sc-bak.log",maxBytes=100,backupCount=2)
logger.addHandler(fh)
ch=logging.StreamHandler()
logger.addHandler(ch)
formatter=logging.Formatter("%(asctime)s - %(filename)s - %(levelname)s:%(message)s")
fh.setFormatter(formatter)
for i in range(200):
#time.sleep(0.5)
logger.warning("this is warining...")
装饰器添加额外功能:
计时
权限控制
日志记录
可以在一个函数上面引用两个装饰器
装饰器带参数:
自身不传入参数的装饰器,使用两层函数定义
自身传入函数的装饰器,使用三层函数定义
import time
def deco(username):
def runtime(func):
def inner(*args,**kwargs):
print(f"装饰器带参数:{username}")
start=time.time()
result=func(*args,**kwargs)
end=time.time()
print(f"{func.__name__}执行花了{end-start}s")
return result
return inner
return runtime
# @deco #add=deco(add)运行的是runtime
@deco(username="sc") #runtime=deco(username="sc") add=runtime(add)
@deco("sc") #这两行效果一样
def add(a,b):
return a+b
add(1,2)
#输出结果:
# 装饰器带参数:sc
# add执行花了0.0s
属性包装装饰器:常常用在设置属性的时候对属性的判断
property 把方法当作属性来使用
class Person():
_age=1
@property
#property本身会创建另外两个装饰器
# @age.setter @age.deleter(被装饰的话名字叫什么 装饰器就叫什么)
def age(self):#把这个age当作属性使用 如果给它赋值则会自动调用age.setter
return self._age
@age.setter
def age(self,num): #这个函数最好与上面重名
if 0<num<140:
self._age=num
else:
raise ValueError("年龄不在范围")
p=Person()
print(p.age)
p.age=110
print(p.age)
#输出结果:1
# 110
#用类去实现装饰器
class A():
def __init__(self,func):
self.func=func
def __call__(self,*args,**kwargs):
print("this is call")
result=self.func(*args,**kwargs)
return result
@A #func1=A(func1)
def func1():
print("i am func1")
func1()
输出结果:
this is call
i am func1
带参数的装饰器用类实现
class A():
def __init__(self, name):
self.name = name
def __call__(self, func):
def inner(*args,**kwargs):
print(self.name)
func(*args,**kwargs)
return inner
#若是不定义新函数 返回原函数
# 那函数不执行时装饰器就已经执行了原函数
@A("sc123")
#a=A("sc")实例化传的参数
# func1=a(func1) 运行的__call__方法
def func123():
print("i am func1")
func123()
装饰器装饰类:
def outer(cls):
def inner(*args,**kwargs):
print(f"class name is {cls.__name__}")
return cls(*args,**kwargs)
return inner
@outer #A=outer(A)
class A:
def __init__(self,name):
self.name=name
a1=A('sc')#输出class name is A