python的学习之路day5

时间:2022-09-09 22:30:53

大纲:

1、双层装饰器

单层装饰器

双层装饰器

原理

2、字符串的格式化

3、format字符串格式化

4、生成器

5、递归

6、模块的安装

7、json模块

8、pickle模块

9、time模块

10、datetime模块

11、logging模块

双层装饰器

还是老样,没有改变:

USER_INFO = {}

def check_login(func):
def inner(*args, **kwargs):
if USER_INFO.get("is_login", None):
# 用get方法拿字典里面的内容,如果字典里面没有我们要拿的参数,不会报错,给他默认返回的为None
ret = func(*args, **kwargs)
return ret
else:
print("请登录") return inner def check_admin(func): # 判断是否为管理员用户
def inner(*args, **kwargs):
if USER_INFO.get("is_login", None):
if USER_INFO.get("user_type", None) == 2: # 如果用户类型等于2,表示为管理员用户
ret = func(*args, **kwargs)
return ret
else:
print("无权限查看") # 否者无权限查看
else:
print("请登录") return inner @check_admin
def index(): # 超级管理员可以查看
print("index") @check_login
def home(): # 登录可以查看
"""
普通用户的功能
:return:
"""
print("home") def login(): # 登录
user = input("请输入用户名:")
if user == "admin":
USER_INFO["is_login"] = True
USER_INFO["user_type"] = 2
else: # 否者如果不为admin,表示登录的用户为普通用户
USER_INFO["is_login"] = True
USER_INFO["is_login"] = 1 def main():
while True:
inp = input("1、登录;2、查看信息;3超级管理员\n>>>")
if inp == "":
login()
elif inp == "":
home()
elif inp == "":
index() main()

v1

输出:

1、登录;2、查看信息;3超级管理员
>>>2
请登录
1、登录;2、查看信息;3超级管理员
>>>3
请登录
1、登录;2、查看信息;3超级管理员
>>>1
请输入用户名:user
1、登录;2、查看信息;3超级管理员
>>>2
home
1、登录;2、查看信息;3超级管理员
>>>3
无权限查看
1、登录;2、查看信息;3超级管理员
>>>1
请输入用户名:admin
1、登录;2、查看信息;3超级管理员
>>>2
home
1、登录;2、查看信息;3超级管理员
>>>3
index
1、登录;2、查看信息;3超级管理员
>>>

v1的输出

新变化:

# 从版本以一中我们可以看到很多我们的check_admin里面重复了check_login的代码(check_admin又判断登录,又判断权限),
# 如果我们又加上了超级管理员,那我们就会又写一个重复的装饰器,
# 所以我们需要用到双层装饰器,先用check_login,判断是否登录,然后用check_admin判断是否为管理员
USER_INFO = {} def check_login(func):
def inner(*args, **kwargs):
if USER_INFO.get("is_login", None):
# 用get方法拿字典里面的内容,如果字典里面没有我们要拿的参数,不会报错,给他默认返回的为None
ret = func(*args, **kwargs)
return ret
else:
print("请登录") return inner def check_admin(func): # 判断是否为管理员用户
def inner(*args, **kwargs):
if USER_INFO.get("user_type", None) == 2: # 如果用户类型等于2,表示为管理员用户
ret = func(*args, **kwargs)
return ret
else:
print("无权限查看") # 否者无权限查看 return inner # 为什么check_login写上面,我们从下向上看,从index()开始,
# 可以看到先用admin装饰后,比如变成了nindex这个函数,然后再用login装饰进行装饰,比如又变成了nnindex,然后python是从上向下执行,
# 所以python会执行nnindex,判断是否登录,然后在执行nindex,判断是否为管理员,如果没有登录,
# 提示登录,如果已经登录(不为管理员),提示无权限
@check_login
@check_admin
def index(): # 管理员可以查看
"""
管理员的功能
:return:
"""
print("index") @check_login
def home(): # 登录可以查看
"""
普通用户的功能
:return:
"""
print("home") def login(): # 登录
user = input("请输入用户名:")
if user == "admin":
USER_INFO["is_login"] = True
USER_INFO["user_type"] = 2
else: # 否者如果不为admin,表示登录的用户为普通用户
USER_INFO["is_login"] = True
USER_INFO["is_login"] = 1 def main():
while True:
inp = input("1、登录;2、查看信息;3超级管理员\n>>>")
if inp == "":
login()
elif inp == "":
home()
elif inp == "":
index() main()

v2

输出:

1、登录;2、查看信息;3超级管理员
>>>2
请登录
1、登录;2、查看信息;3超级管理员
>>>3
请登录
1、登录;2、查看信息;3超级管理员
>>>1
请输入用户名:user
1、登录;2、查看信息;3超级管理员
>>>2
home
1、登录;2、查看信息;3超级管理员
>>>3
无权限查看
1、登录;2、查看信息;3超级管理员
>>>1
请输入用户名:admin
1、登录;2、查看信息;3超级管理员
>>>2
home
1、登录;2、查看信息;3超级管理员
>>>3
index
1、登录;2、查看信息;3超级管理员
>>>

v2的输出

输出效果完全一样,注意看v2的注释

装饰器的原理(多层原理也一样):

python的学习之路day5

字符串的格式化:

%[(name)] [flags] [width].[precision] typecode
# 字符串格式化
# %[(name)] [flags] [width].[precision] typecode # 常规的格式化
string = "博客网址:www.cnblogs.com/%s,园龄:%d个月" % ("smelond", 1)
print(string) # %[(name)]可选,用于指定的key:
string = "博客网址:www.cnblogs.com/%(name)s,园龄:%(age)d个月" % {"name": "smelond", "age": 1} # 用字典方式
print(string) # flags 可选,可供选择的值有(听说没卵用)
# + 右对齐:正数前加正号,负数前加负号
# - 左对齐:正数前无符号,负数前加负号
# 空格 右对齐:正数前加空格,负数前加负号
# 0 右对齐:正数前无符号,负数前加负号;用0填充空白处
string = "博客网址:www.cnblogs.com/%(name)+20s,园龄:%(age)-10d个月" % {"name": "smelond", "age": 1} # 占有20个空格,smelond在其中,向右对齐
print(string) # width 可选,占有宽度 # .precision 可选,小数点后保留的位数
string = "数值:%(p).2f" % {"p": 1.23656} # 在后面加上.然后数字,代表保留几位,有四舍五入功能
print(string) # typecode 必选
# s,获取传入对象的__str__方法的返回值,并将其格式化到指定位置
# r,获取传入对象的__repr__方法的返回值,并将其格式化到指定位置(面向对象内容)
# c,整数:将数字转换成其unicode对应的值,10进制范围为 0 <= i <= 1114111(py27则只支持0-255);字符:将字符添加到指定位置
# o,将整数转换成 八 进制表示,并将其格式化到指定位置
# x,将整数转换成十六进制表示,并将其格式化到指定位置
string = "%c___%o___%x" % (65, 15, 15) # 将十进制转换为其他进制(A,17,f)
print(string) # d,将整数、浮点数转换成 十 进制表示,并将其格式化到指定位置
# e,将整数、浮点数转换成科学计数法,并将其格式化到指定位置(小写e)
# E,将整数、浮点数转换成科学计数法,并将其格式化到指定位置(大写E)
# f, 将整数、浮点数转换成浮点数表示,并将其格式化到指定位置(默认保留小数点后6位)
# F,同上
string = "%d--------%f--------%e--------%E-------%.2ef" % (100000000, 1.23456, 10000000, 10000000, 10000000)
print(string) # g,自动调整将整数、浮点数转换成 浮点型或科学计数法表示(超过6位数用科学计数法),并将其格式化到指定位置(如果是科学计数则是e;)
# G,自动调整将整数、浮点数转换成 浮点型或科学计数法表示(超过6位数用科学计数法),并将其格式化到指定位置(如果是科学计数则是E;)
string = "%g-------%g-------%G-------%G" % (10000000, 100, 10000000, 100)
print(string) # %,当字符串中存在格式化标志时,需要用 %%表示一个百分号
string = "name:%s %% %%%%" % "smelond" # 如果需要输出一个%,但是前面已经有了一个占位符,那就需要输出%%才能代表一个%,否者会报错,需要输出%%,就需要%%%%
print(string)
#
# 注:Python中百分号格式化是不存在自动将整数转换成二进制表示的方式

string_formating.py

博客网址:www.cnblogs.com/smelond,园龄:1个月
博客网址:www.cnblogs.com/smelond,园龄:1个月
博客网址:www.cnblogs.com/ smelond,园龄:1 个月
数值:1.24
A___17___f
100000000--------1.234560--------1.000000e+07--------1.000000E+07-------1.00e+07f
1e+07-------100-------1E+07-------100
name:smelond % %%

输出

format格式化:

# [[fill]align] [sign] [#] [0] [widht] [,] [.precision] [type]
# fill         【可选】空白处填充的字符
# align 【可选】对齐方式(需配合width使用)
# < ,内容左对齐
# > ,内容右对齐(默认)
# =,内容右对齐,将符号放置在填充字符的左侧,且只对数字类型有效。 即使:符号 + 填充物 + 数字
# ^ ,内容居中 # sign 【可选】有无符号数字
# +,正号加正,负号加负;
# -,正号不变,负号加负;
# 空格 ,正号空格,负号加负; # # 【可选】对于二进制、八进制、十六进制,如果加上#,会显示 0b/0o/0x,否则不显示
# , 【可选】为数字添加分隔符,如:1, 000, 000
# width 【可选】格式化位所占宽度
# .precision 【可选】小数位保留精度
# type 【可选】格式化类型
# 传入” 字符串类型 “的参数
# s,格式化字符串类型数据
# 空白,未指定类型,则默认是None,同s
# 传入“ 整数类型 ”的参数
# b,将10进制整数自动转换成2进制表示然后格式化
# c,将10进制整数自动转换为其对应的unicode字符
# d,十进制整数
# o,将10进制整数自动转换成8进制表示然后格式化;
# x,将10进制整数自动转换成16进制表示然后格式化(小写x)
# X,将10进制整数自动转换成16进制表示然后格式化(大写X)
# 传入“ 浮点型或小数类型 ”的参数
# e, 转换为科学计数法(小写e)表示,然后格式化;
# E, 转换为科学计数法(大写E)表示,然后格式化;
# f , 转换为浮点型(默认小数点后保留6位)表示,然后格式化;
# F, 转换为浮点型(默认小数点后保留6位)表示,然后格式化;
# g, 自动在e和f中切换
# G, 自动在E和F中切换
# % ,显示百分比(默认显示小数点后6位)

# 两个最基本的格式化
string = "asdfasgsdf__{0}__asdf__{0}__adhkg__{1}__".format(123, "smelond")
print(string) # asdfasgsdf__123__asdf__123__adhkg__smelond__
string = "___{name:s}___{age:d}___{name:s}".format(name="smelond", age=16)
print(string) # ___smelond___16___smelond # 一些常用的用法
# 空白处填充*,^字符居中,20个空格,s:字符串形式{:*^20s}
# +有符号数值,d:十进制{:+d}
# x 直接转换为16进制
# #如果后面输入的为x,那就转换为16进制后再前面加上0x{:#x}
string = "_____{:*^20s}_____{:+d}_____{:x}_____{:#x}".format("smelond", 123, 15, 15)
print(string) # _____******smelond*******_____+123_____f_____0xf string = "百分比:{:%}".format(1.2345)
print(string) # 百分比:123.450000%

用法

# 一些常用的用法
tpl = "i am {},age {},{}".format("seven", 16, "smelond")
print(tpl) # i am seven,age 16,smelond tpl = "i am {},age {},{}".format(*["seven", 16, "smelond"])
print(tpl) # i am seven,age 16,smelond,注意,如果是列表要在前面加上* tpl = "i am {0},age {1}, really {0}".format("seven", 16)
print(tpl) # i am seven,age 16, really seven tpl = "i am {0},age {1}, really {0}".format(*["seven", 16])
print(tpl) # i am seven,age 16, really seven,列表需要加上* tpl = "i am {name}, age {age}, really {name}".format(name="smelond", age=16)
print(tpl) # i am smelond, age 16, really smelond tpl = "i am {name}, age {age}, really {name}".format(**{"name": "smelond", "age": 16})
print(tpl) # i am smelond, age 16, really smelond,注意,如果是字典需要加上两个* tpl = "i am {0[0]}, age {0[1]}, really {1[2]}".format([1, 2, 3], [11, 22, 33])
print(tpl) # i am 1, age 2, really 33,列表里面的列表 tpl = "i am {:s}, age {:d}".format("smelond", 16)
print(tpl) # i am smelond, age 16 tpl = "i am {name:s}, age {age:d}".format(name="smelond", age=16)
print(tpl) # i am smelond, age 16 tpl = "i am {name:s}, age {age:d}".format(**{"name": "smelond", "age": 16})
print(tpl) # i am smelond, age 16,字典需要加上** tpl = "numbers:{:b},{:o},{:d},{:x},{:X},{:%}".format(15, 15, 15, 15, 15, 15.87612)
print(tpl) # s:1111,17,15,f,F,1500.000000% tpl = "numbers:{0:b},{0:o},{0:d},{0:x},{0:X},{0:%}".format(15)
print(tpl) # s:1111,17,15,f,F,1500.000000% tpl = "numbers:{num:b},{num:o},{num:d},{num:x},{num:X},{num:%}".format(num=15)
print(tpl) # s:1111,17,15,f,F,1500.000000%

一些常用的用法

生成器的使用(生成器是使用函数创建的):

# 普通函数
# def func():
# return 123
#
#
# ret = func() # 执行函数拿结果 # 生成器
def func():
# print("start")
print(111)
yield 1
print(222)
yield 2
print(333)
yield 3 # 如果在函数里面出现了yield,这个函数就称之为生成器 ret = func()
print(ret)
# for i in ret:
# print(i) # 输出
# 循环第一次的时候就进入func函数里面去,进入后拿走yield后面的值,所以输出1,然后循环第二次,
# 第二次进入func函数时,找到上一次结尾的位置,从结尾的位置又开始循环(往下走),所以就是输出2
# 然后第三次
r1 = ret.__next__() # 进入函数找到yield,获取yield后面的数据,然后我们就拿到了1
print(r1)
r2 = ret.__next__() # 进入函数找到yield,获取yield后面的数据,然后我们就拿到了2
print(r2)
r3 = ret.__next__() # 进入函数找到yield,获取yield后面的数据,然后我们就拿到了3
print(r3) # r4 = ret.__next__()
# print(r4) # 从函数里面可以看到没有第4个yield,所以这句要报错 #输出:
111
1
222
2
333
3

生成器的使用

# 基于生成器实现range功能
def myrange(arg): # 相当于这是一个生成器
start = 0
while True:
if start > arg:
return
yield start
start += 1 ret = myrange(3)
# for i in ret:
# print(i)
r = ret.__next__()
print(r)
r = ret.__next__()
print(r)
r = ret.__next__()
print(r)
r = ret.__next__()
print(r)
# r = ret.__next__()
# print(r)#第四次肯定报错,因为只循环3次,从0开始 输出:
0
1
2
3

基于生成器实现range功能

python的递归:

自己拿着windows自带的画图工具画的,将就看吧,是有点丑

python的学习之路day5

代码贴上

# 一个递给另外一个,一个简单的原理
def d():
r = "end" # 将字符串end赋给r
return r # 返回一个变量r def c():
r = d() # 拿到函数d的返回值
return r def b():
r = c() # 拿到函数c的返回值
return r def a():
r = b() # 拿到函数b的返回值
print(r) # 拿到结果后输出 a() # 输出end # 递归
# 执行第一次时的效果
def func(n): # 现在n=1
n += 1 # n等于2
if n >= 4: # 当如果n>=4的时候
return "end" # 遇到return直接退出,然后返回一个字符串end
return func(n) # 上面if如果没执行,肯定会执行这句,返回func函数,现在的n=2 r = func(1) # 传入实参1到func函数里去慢慢执行,然后接收返回值
print(r) #输出end

递归

用递归实现一个1*2*3*4*5*6*7:

def func(n, x):  # n=1,x=1.......n=2,x=2.......n=3,x=6
n += 1 # n=2.......n=3.......n=4
x *= n # x=x*n,x=2.......x=x*n,x=6.......x=x*n,x=24
if n >= 7: # 直到n等于7的时候,将x返回
return x
return func(n, x) # n=2,x=2.......n=3,x=6....... r = func(1, 1)
print(r) 输出:5040

我的思路

def func(num):
if num == 1:
return 1
return num * func(num - 1) x = func(7)
print(x) 输出:5040

老师的思路

事实证明,我太笨了,我那个太复杂了,而且全是运算,但是老师的感觉就轻快明了

模块的使用及安装

# 导入模块
# 单模块
import call_m # 直接调用当前目录下的call_m.py文件
import lib.commons # 调用lib目录下的commons.py文件
# 嵌套在文件夹下的模块
from lib import commons
from src import commons as xxx # 如果重名,我们可以用as给他做一个别名 # call_m.login() # 输出里面的方法,就相当于调用了里面的函数
# lib.commons.logout()

模块

安装requests模块

  pip3 install requests

json模块

json只能处理基本的数据类型

import json

# json只能处理基本的数据类型
dic = {"k1": "v1"}
print(dic, type(dic))
# 用json模块将python的基本数据类型转换成为字符串形式
result = json.dumps(dic)
print(result, type(result)) s1 = '{"k1":123}'
# json将python字符串形式转换成为基本数据类型
dic = json.loads(s1)
print(dic, type(dic)) # py基本数据类型转换字符串
r = json.dumps([11, 22, 33])
# li = "['smelond','amanda']" #这种方法不行,因为其他语言里面 ' 和 "跟python不一样
li = '["smelond","amanda"]' # 反序列化时,一定要使用 "
print(r, type(r))
ret = json.loads(li)
print(ret, type(ret)) li = [11, 22, 33]
json.dump(li, open("db", "w")) # dump先把他进行序列化,然后写到文件里面
li = json.load(open("db", "r")) # 从文件里面把字符串读出来,读出来后会转换成为列表类型
print(li, type(li))

用json加requests模块调用天气的api接口

import json
import requests
import sys
response = requests.get("http://www.sojson.com/open/api/weather/json.shtml?city=双流")
response.encoding = "utf-8"
dic = json.loads(response.text)
print(dic)

json/pickle
json更加适合跨语言操作,因为它传递的是字符串,基本数据类型
pickle,对python的所有类型的序列化,仅适用与python

pickle模块

pickle支持任何的类型

# pickle支持任何的类型
import pickle # dumps a loads
li = [11, 22, 33]
r = pickle.dumps(li) # 字符方式
print(r) result = pickle.loads(r)
print(result) # dump a load
li = [11, 22, 33]
pickle.dump(li, open("db", "wb")) ##pickle是以字符方式存取,所以要加上b resul = pickle.load(open("db", "rb")) # 读取
print(resul)

time&datetime模块

time模块

import time

print(time.process_time())  # 测量处理器运算时间,不包括sleep时间,不稳定
print(time.altzone) # 返回与utc时间的时间差,以秒计算
print(time.asctime()) # 返回时间格式“Sat Dec 30 17:32:59 2017”
print(time.localtime()) # 返回本地时间的struct time对象格式
tm = time.localtime() # 将返回的struct time格式的时间赋给tm
print("{}-{}".format(tm.tm_year, tm.tm_mon)) # 用format输出年月
print(time.gmtime(time.time() - 8000000)) # 返回utc时间的struc时间对象格式
print(time.asctime(time.localtime())) # 返回时间格式“Sat Dec 30 17:39:47 2017”
print(time.ctime()) # 返回时间格式“Sat Dec 30 17:41:44 2017”同上 # 日期字符串 转换 时间戳
string_2_struct = time.strptime("2017/12/30", "%Y/%m/%d") # 将日期字符串 转换 struct时间对象格式
print(string_2_struct) struct_2_stamp = time.mktime(string_2_struct) # 将struct时间对象转换成为时间戳
print(struct_2_stamp)
print(time.ctime(struct_2_stamp)) # 返回时间为“Sat Dec 30 00:00:00 2017”格式 # 将时间戳转为字符串格式
print(time.gmtime(time.time() - 86640)) # 将utc时间戳转换struct_time格式
print(time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())) # 将utc struct_time格式转换成指定的字符串格式
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) # 将本地 struct_time格式转换成指定的字符串格式

datetime模块

import datetime

print(datetime.datetime.now())  # 返回“2017-12-30 17:56:40.261813”
print(datetime.date.fromtimestamp(time.time())) # 时间戳直接转换成为日期格式“2017-12-30”
# 时间加减
print(datetime.datetime.now())
print(datetime.datetime.now() + datetime.timedelta(3)) # 当前时间+3天
print(datetime.datetime.now() + datetime.timedelta(-3)) # 当前时间-3天
print(datetime.datetime.now() + datetime.timedelta(hours=3)) # 当前时间+3小时
print(datetime.datetime.now() + datetime.timedelta(minutes=30)) # 当前时间+30分钟 c_time = datetime.datetime.now()
# print(c_time.replace(minute=3, hour=2)) # 时间替换,替换小时和分钟
print(c_time.replace(hour=2, minute=3)) # 时间替换,替换小时和分钟

logging模块

logging模式是一个日志模块,很多程序都需要一个记录日志,所以python为我们提供了这么一个模块,logging的日志分为5个等级:debug(),waring(),error(),critical()

日志等级(数字越大,表示危害越高):

critical = 50

error = 40

warning = 30

info = 20

debug = 10

注意:只有【当前写等级】大于【日志等级】时,日志文件才被记录

日志输出,最简单的用法:

import logging

logging.warning("user [smelond] attempted wrong password more than 3 times")  # 可以直接输出到屏幕上
logging.critical("server is down")

将日志输出到文件里面:

import logging
logging.basicConfig(filename='example.log', level=logging.INFO) # 设置将输出内容保存到example.log
# level=loggin.INFO意思是,把日志纪录级别设置为INFO,也就是说,只有比日志是INFO或比INFO级别更高的日志才会被纪录到文件里
logging.debug("this message should go to the log file") # 不会保存到日志文件里面
logging.info("So should this") # 日志级别也为info,所以可以保存到文件
logging.warning("And this,too") # 这个等级大于info,所以也可以保存到文件里面

将日志输出到文件里面,并且加上时间:

logging.basicConfig(filename='example.log', level=logging.INFO, format="%(asctime)s (message)s", datefmt="%m%d%Y %H:%M:%S %p")  # format格式化输出,后面放时间格式
# level=loggin.INFO意思是,把日志纪录级别设置为INFO,也就是说,只有比日志是INFO或比INFO级别更高的日志才会被纪录到文件里
logging.debug("this message should go to the log file") # 不会保存到日志文件里面
logging.info("So should this") # 日志级别也为info,所以可以保存到文件
logging.warning("And this,too") # 这个等级大于info,所以也可以保存到文件里面
logging.warning("is when this event was logged.") # 大于info 输出:
01012018 20:16:36 PM So should this
01012018 20:16:36 PM And this,too
01012018 20:16:36 PM is when this event was logged.

以下来自alex li

日志输出格式:

%(name)s

Logger的名字

%(levelno)s

数字形式的日志级别

%(levelname)s

文本形式的日志级别

%(pathname)s

调用日志输出函数的模块的完整路径名,可能没有

%(filename)s

调用日志输出函数的模块的文件名

%(module)s

调用日志输出函数的模块名

%(funcName)s

调用日志输出函数的函数名

%(lineno)d

调用日志输出函数的语句所在的代码行

%(created)f

当前时间,用UNIX标准的表示时间的浮 点数表示

%(relativeCreated)d

输出日志信息时的,自Logger创建以 来的毫秒数

%(asctime)s

字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒

%(thread)d

线程ID。可能没有

%(threadName)s

线程名。可能没有

%(process)d

进程ID。可能没有

%(message)s

用户输出的消息

logging模块记录日志涉及到的四个主要类:

logger提供了应用程序可以直接使用接口

handler将(logging创建)日志记录发送到合适的目的输出

filter提供了细度设备来决定输出哪条日志记录

formatter决定日志记录的最终输出格式

logger
每个程序在输出信息之前都要获得一个Logger。Logger通常对应了程序的模块名,比如聊天工具的图形界面模块可以这样获得它的Logger:
LOG=logging.getLogger(”chat.gui”)
而核心模块可以这样:
LOG=logging.getLogger(”chat.kernel”)

Logger.setLevel(lel):指定最低的日志级别,低于lel的级别将被忽略。debug是最低的内置级别,critical为最高
Logger.addFilter(filt)、Logger.removeFilter(filt):添加或删除指定的filter
Logger.addHandler(hdlr)、Logger.removeHandler(hdlr):增加或删除指定的handler
Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical():可以设置的日志级别

handler

handler对象负责发送相关的信息到指定目的地。Python的日志系统有多种Handler可以使用。有些Handler可以把信息输出到控制台,有些Logger可以把信息输出到文件,还有些

Handler可以把信息发送到网络上。如果觉得不够用,还可以编写自己的Handler。可以通过addHandler()方法添加多个多handler
Handler.setLevel(lel):指定被处理的信息级别,低于lel级别的信息将被忽略
Handler.setFormatter():给这个handler选择一个格式
Handler.addFilter(filt)、Handler.removeFilter(filt):新增或删除一个filter对象

每个Logger可以附加多个Handler。接下来我们就来介绍一些常用的Handler:
1) logging.StreamHandler
使用这个Handler可以向类似与sys.stdout或者sys.stderr的任何文件对象(file object)输出信息。它的构造函数是:
StreamHandler([strm])
其中strm参数是一个文件对象。默认是sys.stderr

2) logging.FileHandler
和StreamHandler类似,用于向一个文件输出日志信息。不过FileHandler会帮你打开这个文件。它的构造函数是:
FileHandler(filename[,mode])
filename是文件名,必须指定一个文件名。
mode是文件的打开方式。参见Python内置函数open()的用法。默认是’a',即添加到文件末尾。

3) logging.handlers.RotatingFileHandler
这个Handler类似于上面的FileHandler,但是它可以管理文件大小。当文件达到一定大小之后,它会自动将当前日志文件改名,然后创建

一个新的同名日志文件继续输出。比如日志文件是chat.log。当chat.log达到指定的大小之后,RotatingFileHandler自动把

文件改名为chat.log.1。不过,如果chat.log.1已经存在,会先把chat.log.1重命名为chat.log.2。。。最后重新创建
chat.log,继续输出日志信息。它的构造函数是:
RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]])
其中filename和mode两个参数和FileHandler一样。
maxBytes用于指定日志文件的最大文件大小。如果maxBytes为0,意味着日志文件可以无限大,这时上面描述的重命名过程就不会发生。
backupCount用于指定保留的备份文件的个数。比如,如果指定为2,当上面描述的重命名过程发生时,原有的chat.log.2并不会被更名,而是被删除。

4) logging.handlers.TimedRotatingFileHandler
这个Handler和RotatingFileHandler类似,不过,它没有通过判断文件大小来决定何时重新创建日志文件,而是间隔一定时间就
自动创建新的日志文件。重命名的过程与RotatingFileHandler类似,不过新的文件不是附加数字,而是当前时间。它的构造函数是:
TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]])
其中filename参数和backupCount参数和RotatingFileHandler具有相同的意义。
interval是时间间隔。
when参数是一个字符串。表示时间间隔的单位,不区分大小写。它有以下取值:
S 秒
M 分
H 小时
D 天
W 每星期(interval==0时代表星期一)
midnight 每天凌晨

将日志文件输出到多个地方:

# 将日志输出到多个地方
import logging # create logger
logger = logging.getLogger('TEST-LOG') # 设置一个名称
logger.setLevel(logging.INFO) # 设置一个最低日志输出等级,设置为了INFO等级,(全局) # create console handler and set level to debug
ch = logging.StreamHandler() # 输出到屏幕上
ch.setLevel(logging.DEBUG) # 设置屏幕输出的最低日志等级但是会发现不能输出debug,因为我们上面的全局配置上最低设置成为了INFO等级,DEBIG>INFO # create file handler and set level to warning
fh = logging.FileHandler("access.log") # 设置输出到文件
fh.setLevel(logging.WARNING) # 设置文件输出的最低等级
# create formatter
formatter_ch = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # 格式化
formatter_fh = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') # 格式化 # add formatter to ch and fh
ch.setFormatter(formatter_ch) # 设置输出到屏幕上的格式
fh.setFormatter(formatter_fh) # 设置输出到日志中的格式 # add ch and fh to logger
logger.addHandler(ch) # 添加handler
logger.addHandler(fh) # 'application' code
logger.debug('debug message') # 输出提示(不能输出到任何地方)
logger.info('info message') # 输出提示(只能输出到屏幕,因为输出到文件最低等级需要WARNING)
logger.warning('warn message') # 输出提示(双方)
logger.error('error message') # 双方
logger.critical('critical message') # 双方 屏幕输出:
2018-01-02 11:44:34,121 - TEST-LOG - INFO - info message
2018-01-02 11:44:34,121 - TEST-LOG - WARNING - warn message
2018-01-02 11:44:34,121 - TEST-LOG - ERROR - error message
2018-01-02 11:44:34,121 - TEST-LOG - CRITICAL - critical message 文件输出:
2018-01-02 11:44:34,121 - WARNING - warn message
2018-01-02 11:44:34,121 - ERROR - error message
2018-01-02 11:44:34,121 - CRITICAL - critical message

python的学习之路day5的更多相关文章

  1. Python入门学习之路,怎么 &OpenCurlyDoubleQuote;开心,高效,踏实” 地把Python学好?兴趣,兴趣,兴趣!

    Python入门学习之路,怎么 “开心,高效,踏实” 地把Python学好?兴趣,兴趣,兴趣!找到你自己感兴趣的点进行切入,并找到兴趣点进行自我驱动是最好的学习方式!       推荐两本书,一本作为 ...

  2. ql的python学习之路-day5

    文件操作 文件操作流程: 1.打开文件得到文件句柄并赋值变量 2.通过句柄对文件进行操作 3.关闭文件 打开的只是储存在计算机里的文件对象,必须赋值一个变量才能操作,变量通常用f表示,赋值f的文件对象 ...

  3. python 爬虫学习之路

    2016-6-18 --今天实现了第一个用urllib2实现的爬虫程序. --过程中发现 req = urllib2.Request(url,headers = headers) 总是报错: 主要原因 ...

  4. python的学习之路day7-socket网络编程

    python基础部分学习完了,时间也已经过了两个月左右,感觉没学到什么,可能是我学习之后忘记的太多了. 由于没钱买书,要是去培训就更没钱了,所以在网上找了一本书,感觉还不错,讲的比较好,比较详细. P ...

  5. python的学习之路day2

    1.什么是常量: 常量在程序中是不变的量 但是在python中所有的变量都可以改 注意:为了防止区分错误,所以python中常量使用大写命名 例如: MYSQL_CONNECTION = '192.1 ...

  6. Python小白学习之路(二十)—【打开文件的模式二】【文件的其他操作】

    打开文件的模式(二) 对于非文本文件,我们只能使用b模式,"b"表示以字节的方式操作(而所有文件也都是以字节的形式存储的,使用这种模式无需考虑文本文件的字符编码.图片文件的jgp格 ...

  7. Python小白学习之路(十五)—【map&lpar;&rpar;函数】【filter&lpar;&rpar;函数】【reduce&lpar;&rpar;函数】

    一.map()函数 map()是 Python 内置的高阶函数 有两个参数,第一个是接收一个函数 f(匿名函数或者自定义函数都OK啦):第二个参数是一个 可迭代对象 功能是通过把函数 f 依次作用在 ...

  8. Python小白学习之路(十)—【函数】【函数返回值】【函数参数】

    写在前面: 昨天早睡之后,感觉今天已经恢复了百分之八十的样子 又是活力满满的小伙郭 今日份鸡汤: 我始终相信,在这个世界上,一定有另一个自己,在做着我不敢做的事,在过着我想过的生活.-------宫崎 ...

  9. Python小白学习之路(九)—【字符串格式化】【百分号方式】【format方式】

    写在前面: 最近的事情好像有很多.李咏的离去,让我觉得很突然,仿佛印象中就是主持节目的他,看着他和哈文的爱情,很是感动.离去,没有什么抱怨,只是遗憾. 总会感慨,时光的流逝. 好像真的很快,转眼间,我 ...

随机推荐

  1. 创建 router 连通 subnet- 每天5分钟玩转 OpenStack(100)

    上一节我们为 Neutron 虚拟路由器配置好了 L3 agent,今天将创建虚拟路由器“router_100_101”,打通 vlan100 和 vlan101. 打开操作菜单 Project -& ...

  2. centos同步北京时间

    yum install ntp ntpdate #ntpdate -u 202.120.2.101 //写入硬件 #hwclock -w 以下是国内常见的NTP服务器 ntp.sjtu.edu.cn ...

  3. openssl rsa 私钥 PKCS8私钥 公钥

    上文配置好 openssl 运行 => cmd => cd C:\usr\local\ssl\bin => 执行 openssl

  4. Linux命令-grep

    grep命令用于对文本进行搜索,格式为“grep [选项] [文件]” 搜索某个关键词:"grep 关键词 文本文件" 参数说明 -b 将可执行文件当做文本文件来搜索 -c 仅显示 ...

  5. BZOJ 1660&colon; &lbrack;Usaco2006 Nov&rsqb;Bad Hair Day 乱发节&lpar; 单调栈 &rpar;

    维护一个h严格递减的栈 , 出栈时计算一下就好了.. ------------------------------------------------------------------------- ...

  6. 首款符合PICO-ITX规格的A20开源硬件开发平台

    http://mp.weixin.qq.com/mp/appmsg/show?__biz=MjM5NzM0MjcyMQ==&appmsgid=10001083&itemidx=2&am ...

  7. iOS pragma mark要使用

    郝萌主倾心贡献,尊重作者的劳动成果.请勿转载. 假设文章对您有所帮助.欢迎给作者捐赠.支持郝萌主,捐赠数额任意.重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 简单的来说 ...

  8. Asp&period;Net Core 中无法使用 ConfigurationManager&period;AppSettings

    刚刚接触.net core ,准备把之前的一些技术常用工具先移植到.net Standard上面来, 方便以后使用,结果用到ConfigurationManager 的 AppSettings 就出现 ...

  9. Vue的土著指令和自定义指令

    1.土著指令 当我开始学习Vue的时候,看官网的时候看到了"指令"两个字.我愣住了,what?指令是啥啊?后来继续往下看,像这种什么"v-for""v ...

  10. Java多态的向上转型和向下转型

    Java多态的向上转型和向下转型 向上转型:(子类转为父类,自动转型) 格式 :父类类型 变量名 = new 子类类型(); 注:子类赋值给父类,那这时这个父类就能调用子类的方法 向下转型:(父类转为 ...