目录
time模块
import time
print(time.time())#获取时间戳 浮点数
print(time.sleep(2))#睡眠,阻塞
print(time.strftime('%Y-%m-%d %H:%M:%S'))#时间显示格式,页面显示的格式
print(time.gmtime())#结构化时间,元祖的形式(命名元祖),可以根据索引和元素进行查找
time.struct_time(tm_year=2019, tm_mon=7, tm_mday=25, tm_hour=8, tm_min=10, tm_sec=50, tm_wday=3, tm_yday=206, tm_isdst=0)
#time.localtime获取的是当地时间
# print(time.gmtime()[0])
# print(time.gmtime().tm_year)
#将时间戳转换成字符串时间
print(time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime(1564028611.631374)))
#将字符串时间转换成时间戳
print(time.mktime(time.strptime("2024-3-16 12:30:30","%Y-%m-%d %H:%M:%S")))
---------------------------------------
重点:
# time重点:
time.time()
time.sleep()
time.gmtime() / time.localtime() #
time.strftime("格式化","结构化时间") #
time.strptime("字符串","格式化")
time.mktime()
****************************************************************
datatime模块
print(type(datetime.now()))获取当前时间,获取的是一个对象
print(datetime(2019,5,21,15,14,00) - datetime(2019,5,20,14,20,00))计算时间差
# 将当前时间转化成时间戳
t = datetime.now()
print(t.timestamp())
-----------------------------------------
# 将时间戳转化成当前时间
import time
print(datetime.fromtimestamp(15000000000))
-----------------------------------------------------
# 将字符串转成对象
print(type(datetime.strptime("2019-10-10 22:23:24","%Y-%m-%d %H:%M:%S")))
-----------------------------------------------------
# 将对象转成字符串
print(str(datetime.now()))
print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
------------------------------------------------------
# datetime加减
print(datetime.now() + timedelta(hours=30 * 24 * 12))
print(datetime.now() - timedelta(hours=30 * 24 * 12))
***********************************************************
# datatime模块
import datetime
now_time = datetime.datetime.now() # 现在的时间
# 只能调整的字段:weeks days hours minutes seconds
print(datetime.datetime.now() + datetime.timedelta(weeks=3)) # 三周后
print(datetime.datetime.now() + datetime.timedelta(weeks=-3)) # 三周前
print(datetime.datetime.now() + datetime.timedelta(days=-3)) # 三天前
print(datetime.datetime.now() + datetime.timedelta(days=3)) # 三天后
print(datetime.datetime.now() + datetime.timedelta(hours=5)) # 5小时后
print(datetime.datetime.now() + datetime.timedelta(hours=-5)) # 5小时前
print(datetime.datetime.now() + datetime.timedelta(minutes=-15)) # 15分钟前
print(datetime.datetime.now() + datetime.timedelta(minutes=15)) # 15分钟后
print(datetime.datetime.now() + datetime.timedelta(seconds=-70)) # 70秒前
print(datetime.datetime.now() + datetime.timedelta(seconds=70)) # 70秒后
current_time = datetime.datetime.now()
# 可直接调整到指定的 年 月 日 时 分 秒 等
print(current_time.replace(year=1977)) # 直接调整到1977年
print(current_time.replace(month=1)) # 直接调整到1月份
print(current_time.replace(year=1989,month=4,day=25)) # 1989-04-25 18:49:05.898601
# 将时间戳转化成时间
print(datetime.fromtimestamp(1232132131)) # 2009-01-17
random模块
print(random.random())#在0~1之间随机生成一个浮点数
print(random.uniform(0,10))#在0~10时间随机生成一个浮点数,可以指定范围
print(random.randint(1,10))#随机生成一个整数,可以指定范围
print(random.randrange(1,5,2))#起始终止步长,生成一个数字
print(random.chioce([1,2,3,4,5,6]))#随机选择一个元素
print(random.chioces([1,2,3,4,5,6,7]),k=2)#随机选择两个元素,会有重复的
print(random.sample((1,2,3,4,5,6,7,8)),k=2)#随机选择两个元素,不会有重复的,除非只有两个
print(random.shuffle(lst))#打乱顺序
*************************************************
>>> import random
#随机小数
>>> random.random() # 大于0且小于1之间的小数
0.7664338663654585
>>> random.uniform(1,3) #大于1小于3的小数
1.6270147180533838
#随机整数
>>> random.randint(1,5) # 大于等于1且小于等于5之间的整数***
>>> random.randrange(1,10,2) # 大于等于1且小于10之间的奇数***
#随机选择一个返回
>>> random.choice([1,'23',[4,5]]) # #1或者23或者[4,5]
#随机选择多个返回,返回的个数为函数的第二个参数***
>>> random.choices([1,2,3,4],k=2) # 选择两个元素,会有重复,可控制元素个数***
>>> random.sample([1,'23',[4,5]],k=2) # #列表元素任意2个组合,不会重复(原列表有重复就会出现重复),可控制元素个数***
[[4, 5], '23']
#打乱列表顺序
>>> item=[1,3,5,7,9]
>>> random.shuffle(item) # 对原列表打乱次序
>>> item
[5, 1, 3, 7, 9]
>>> random.shuffle(item)
>>> item
[5, 9, 7, 1, 3]
序列化模块
-
json
1.dumps loads lit = [1,22,3,3,45] print(json.dumps(lit),type(json.dumps(lit))) str_lst = json.dumps(lit) lst = json.loads(str_lst) print(lst,type(lst)) dumps 将对象转换(序列化)成字符串 loads 将字符串转换(反序列化)成对象 dic = {'username':'宝元'} str_dic = json.dumps(dic) # 序列化 str_dic = json.dumps(dic,ensure_ascii=False) # ensure_ascii=False 关闭ascii码 print(str_dic,type(str_dic)) dic1 = json.loads(str_dic) # 反序列化 print(dic1,dic1["username"]) 2.dump load import json lit = [1,22,3,3,45] 同时写多个内容 进行序列化 lst = [1,2,3,4,56,] f = open("info","w",encoding="utf-8") f.write(json.dumps(lst) + " ") f.write(json.dumps(lst) + " ") f.write(json.dumps(lst) + " ") f.write(json.dumps(lst) + " ") f.write(json.dumps(lst) + " ") f.close() dump: 将对象转换(序列化)成字符串,写入文件 load: 将文件中字符串转换(反序列)成对象 同时读多个内容进行反序列 f1 = open("info","r",encoding="utf-8") for i in f1: l = json.loads(i) print(l) f1.close()
-
pickle模块
pickle 序列化 - nb(python所有对象进行转换) python自带的(只有python可以用) 两组4个方法: 1. dumps loads import pickle lst = [12,3,4,5,768] t_list = pickle.dumps(lst) # 转换成类似字节 print(t_list) print(pickle.loads(t_list)[-1]) dic = {"user":"郭宝元"} t_list = pickle.dumps(dic) # 转换成类似字节 print(t_list) print(pickle.loads(t_list)) def func(): print(111) import json fun = json.dumps(func) print(fun) fun = pickle.dumps(func) print(fun) pickle.loads(fun)() 2. dump load import pickle dic = {"usern":"baoyuian"} dic = {"usern":"宝元"} pickle.dump(dic,open("info","wb")) print(pickle.load(open("info","rb"))) import pickle dic = {"user":"123"} pickle.dump(dic,open("info","ab")) import pickle dic = {"1":2} f = open("info","wb") s = " ".encode("utf-8") f.write(pickle.dumps(dic)+ s) f.write(pickle.dumps(dic)+ s) f.write(pickle.dumps(dic)+ s) f.close() f1 = open("info","rb") for i in f1: print(pickle.loads(i)) 推荐使用json json是各种语言通用的
os模块
-
os模块是程序员通过python向操作系统发送指令的交互接口
import os #工作目录 print(os.getcwd())#获取当前的工作路径 print(os.chdir())#修改工作路径 print(os.curdir) print(os.pardir) #文件夹 print(os.mkdir('aaa')) print(os.rmdir('aaa')) print(os.makedirs('aaa/bbb/ccc')) print(os.removedirs('aaa/bbb/ccc')) print(os.listdir('E:python24期笔记day17')) #文件相关 print(os.rename('aa.txt','bb.txt'))#修改文件名 print(os.remove('sss'))#删除文件 #路径相关 print(os.path.abspath('F:oldboyday17os模块.py'))#获取绝对路径 print(os.path.dirname('F:oldboyday17os模块.py'))#获取文件夹路径 print(os.path.basename('F:oldboyday17os模块.py'))#获取文件目录 print(os.path.split('F:oldboyday17os模块.py'))#对文件夹和文件分割 print(os.path.isabs('F:oldboyday17os模块.py'))#判断是不是绝对路径 print(os.path.isdir('F:oldboyday17'))#判断是不是一个目录 print(os.path.isfile('F:oldboyday17os模块.py'))#判断是不是一个文件名 print(os.path.exists('F:oldboyday17os模块.py'))#判断路径存不存在 print(os.path.join())#拼接路径 os.path.getatime()#查看文件的最后访问时间 os.path.getmtime()#查看文件的最后修改时间 os.path.getctime()#文件的创建时间 os.path.getsize()#路径的字节大小,按照kb返回
hashlib模块
md5,sha1,sha256,sha512
1.只要明文相同密文就是相同的
2.只要明文不相同密文就是不相同的
3.不能反逆(不能解密) -- md5中国人破解了
加密:
1.加密的内容
2.将要加密的内容转成字节
#最常用是的md5,平时加密的时候使用sha1
#加固定盐
import hashlib
md5 = hashlib.md5("常鑫".encode("utf-8"))
md5.update("alex123".encode("utf-8"))
print(md5.hexdigest())
md5 = hashlib.md5()
md5.update("alex123".encode("utf-8"))
print(md5.hexdigest())
#动态加盐
user = input("username:")
pwd = input("password")
import hashlib
md5 = hashlib.md5(user.encode("utf-8"))
md5.update(pwd.encode("utf-8"))
print(md5.hexdigest())
md5 = hashlib.md5()
md5.update(pwd.encode("utf-8"))
print(md5.hexdigest())
#767db14ed07b245e24e10785f9d28e29
f = open(r"F:s24day17python-3.6.6-amd64.exe","rb")
import hashlib
md5 = hashlib.md5()
md5.update(f.read())
print(md5.hexdigest())
ss = "baoyuanalextaibai"
s = "baoyuan"
s1 = "alex"
s2 = "taibai"
import hashlib
md5 = hashlib.md5()
md5.update(ss.encode("utf-8"))
print(md5.hexdigest())
md5 = hashlib.md5()
md5.update(s.encode("utf-8"))
md5.update(s1.encode("utf-8"))
md5.update(s2.encode("utf-8"))
print(md5.hexdigest())
#节省内存
f = open(r"F:s24day17python-3.6.6-amd64.exe","rb")
import hashlib
md5 = hashlib.md5()
while True:
msg = f.read(1024)
if msg:
md5.update(msg)
else:
print(md5.hexdigest())
break
collections模块
collections模块
在内置数据类型(dict、list、set、tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter、deque、defaultdict、namedtuple和OrderedDict等。
1.namedtuple: 生成可以使用名字来访问元素内容的tuple
2.deque: 双端队列,可以快速的从另外一侧追加和推出对象
3.Counter: 计数器,主要用来计数
4.OrderedDict: 有序字典
5.defaultdict: 带有默认值的字典
====================================================================================
#namedtuple
我们知道tuple可以表示不变数据,例如,一个点的二维坐标就可以表示成:
p = (1, 2)
但是,看到(1, 2),很难看出这个tuple是用来表示一个坐标的。
这时,namedtuple就派上了用场:
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(1, 2)
print(p)
结果:Point(x=1, y=2)
类似的,如果要用坐标和半径表示一个圆,也可以用namedtuple定义:
namedtuple('名称', [属性list]):
Circle = namedtuple('Circle', ['x', 'y', 'r'])
deque
使用list存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低。
----------------------------------------------------------------------------------
#deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:
from collections import deque
q = deque(['a', 'b', 'c'])
q.append('x')
q.appendleft('y')
q
deque(['y', 'a', 'b', 'c', 'x'])
deque除了实现list的append()和pop()外,还支持appendleft()和popleft(),这样就可以非常高效地往头部添加或删除元素。
------------------------------------------------------------------------
#OrderedDict
使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序。
如果要保持Key的顺序,可以用OrderedDict:
from collections import OrderedDict
d = dict([('a', 1), ('b', 2), ('c', 3)]) # 另一种定义字典的方式
print(d)
# 结果:
{'a': 1, 'c': 3, 'b': 2}
od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
print(od)
# 结果:
OrderedDict([('a', 1), ('b', 2), ('c', 3)])
注意,OrderedDict的Key会按照插入的顺序排列,不是Key本身排序:
>>> od = OrderedDict()
>>> od['z'] = 1
>>> od['y'] = 2
>>> od['x'] = 3
>>> od.keys() # 按照插入的Key的顺序返回
['z', 'y', 'x']
--------------------------------------------------------------------------
#defaultdict
有如下值集合 [11,22,33,44,55,66,77,88,99,90...],将所有大于 66 的值保存至字典的第一个key中,将小于 66 的值保存至第二个key的值中。
即: {'k1': 大于66 , 'k2': 小于66}
li = [11,22,33,44,55,77,88,99,90]
result = {}
for row in li:
if row > 66:
if 'key1' not in result:
result['key1'] = []
result['key1'].append(row)
else:
if 'key2' not in result:
result['key2'] = []
result['key2'].append(row)
print(result)
from collections import defaultdict
values = [11, 22, 33,44,55,66,77,88,99,90]
my_dict = defaultdict(list)
for value in values:
if value>66:
my_dict['k1'].append(value)
else:
my_dict['k2'].append(value)
使用dict时,如果引用的Key不存在,就会抛出KeyError。如果希望key不存在时,返回一个默认值,就可以用defaultdict:
from collections import defaultdict
dd = defaultdict(lambda: 'N/A')
dd['key1'] = 'abc'
# key1存在
print(dd['key1'])
dd['key2'] # key2不存在,返回默认值
print(dd['key2'])
-------------------------------------------------
#Counter
Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。计数值可以是任意的Interger(包括0和负数)。Counter类和其他语言的bags或multisets很相似。
c = Counter('abcdeabcdabcaba')
print c
输出:Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1})
re模块
s='lijie_李杰_l lilililijiee123@'
#w匹配字母数字,下划线包括中文
print(re.findall('w',s))
#W匹配非字母数字,下划线包括中文
print(re.findall('W',s))
#s匹配任意空格,换行符,制表符
print(re.findall('s',s))
#S匹配非任意空格,换行符,制表符
print(re.findall('S',s))
#d匹配数字
print(re.findall('d',s))
#D匹配非数字
print(re.findall('D',s))
#A或^匹配开头的内容
print(re.findall('Alijie',s))
print(re.findall('^lijie',s))
#或$匹配结尾的内容
print(re.findall('123@',s))
print(re.findall('123@$',s))
#
匹配换行符和制表符
print(re.findall('
',s))
print(re.findall(' ',s))
#.匹配任意一个内容(换行符除外)
print(re.findall('l.j',s))
print(re.findall('l.j',s,re.DOTALL))#.匹配任意时,可以匹配所有
#[]指定匹配的范围
print(re.findall('[A-Za-z0-9]',s))
#[^]匹配指定范围之外的
print(re.findall('[^a-z]',s))
#*匹配0个或多个内容
print(re.findall('li*',s))#贪婪匹配
#+匹配1个或多个内容
print(re.findall('li',s))#贪婪匹配
#?匹配0个或一个内容
print(re.findall('li?',s))
#{}重复匹配指定字符几次
print(re.findall('l{1}',s))
#{1,6}指定重复匹配指定字符的次数范围
print(re.findall('l{1,6}',s))
#|或者
print(re.findall('li|jie',s))
#()匹配括号里的内容
print(re.findall('l(.+?)j',s))
print(re.findall('l(?:.+?)l',s))#()匹配时?:可以将括号外面的一起返回
#search匹配一个,匹配到返回的是一个对象,查看元素用group()方法
print(re.search('li',s))
#match从字符串的开头查找,返回一个对象,查看元素用group()方法
print(re.match('li',s))
#finditer返回一个迭代器
a=re.finditer('w','你好世界')
print(next(a).group())#用group查看值
#split分割
print(re.split('l',s))
#sub替换
print(re.sub('li','哈哈','lijieljie'))
#?P分组起名
print(re.findall('(?P<aaa>w)jie',s).group('aaa'))
#.转义
# 匹配所有的数字(包含小数包含负号)
# print(re.findall("-?d+.d+|-?d+",s))
元字符 |
匹配内容 |
---|---|
w | 匹配字母(包含中文)或数字或下划线 |
W | 匹配非字母(包含中文)或数字或下划线 |
s | 匹配任意的空白符 |
S | 匹配任意非空白符 |
d | 匹配数字 |
D | p匹配非数字 |
A | 从字符串开头匹配 |
z | 匹配字符串的结束,如果是换行,只匹配到换行前的结果 |
匹配一个换行符 | |
匹配一个制表符 | |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结尾 |
. | 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。 |
[...] | 匹配字符组中的字符 |
[^...] | 匹配除了字符组中的字符的所有字符 |
* | 匹配0个或者多个左边的字符。 |
+ | 匹配一个或者多个左边的字符。 |
? | 匹配0个或者1个左边的字符,非贪婪方式。 |
{n} | 精准匹配n个前面的表达式。 |
{n,m} | 匹配n到m次由前面的正则表达式定义的片段,贪婪方式 |
a|b | 匹配a或者b。 |
() | 匹配括号内的表达式,也表示一个组 |
模块和包
只要文件夹下含有__init__.py文件就是一个包,包是干什么的呢?
回想一下,之前我们没有学习模块的时候将一个整体的功能写入到文件中,为了能够充分的将某个功能进行重用 我们使用了模块,但是慢慢的模块就会越来越多.我们想提高程序的结构性可维护性,就使用包将模块进行统一管理
包能够管理多个模块,我们想要使用包里的模块怎么办呢?
使用import 和from xx import xx 现有如下结构
bake
├── __init__.py
├── api
├── __init__.py
├── policy.py
└── versions.py
├── cmd
├── __init__.py
└── manage.py
└── db
├── __init__.py
└── models.py
我们在bake同级创建一个test.py进行导入policy.py 我们使用模块的import的时候只能将api添加到sys.path的路劲中,我们来看看包使用import导入
import bake.api.policy
bake.api.policy.get()
导入的太长了下边使用的时候还需要在重复写一遍,我们可以使用as起别名
import bake.api.policy as p
p.get()
这样的操作只支持包,普通的文件夹无效,有人一定在想我把bake拿过来然后一层一层的打开那拿工具就可以了
import bake
bake.api.policy.get()
不好使,这样导入是只将policy导入了,有人想怎么将api包下的模块全部导入不要急,先说单独导入的方式
咱们能够使用import进行导入,在来看看from的导入方式
from bake.api import policy
policy.get()
from bake import api
print(api.versions.name)
还是不好使,通过这两个我们能够感觉都导入的时候指定要导入的内容,不能再导入后在进行开箱子
我们现在说了单独导入一个模块,现在来说道说道怎么导入某个包下的所有模块,想要导入某个包下的所有的模块 我们就需要在包中的__init__.py做点手脚
bake包下的__init__.py
from . import api
.是当前路径,因为from的时候不能空着
api包下的__init__.py
from . import policy
我们将包下的__init__配置好,然后在test.py进行导入
import bake
bake.api.policy.get()
又好使了,这是为什么呢?我们import导入bake这个包,因为bake是一个文件夹不能进行任何操作,就让__init__.py代替它 去将api这包中的模块导入,api也是一个文件夹不能操作就需要让api下边的__init__.py去找api下边的两个模块
这个和公司的上下级关系一样,打比方现在test.py就是一个ceo要和policy这个小员工谈话,ceo先把这个想法人事经理,人事经理就是 bake这个包,人事经理通知人事让人事查找一下policy在那个部门,人事查到后通知部门的负责人,部门的负责人在通知部门的主管,主管告诉policy这个员工, 说ceo要找你,部门的主管带着policy去找人事,人事带着policy,人事然后在带着policy去找ceo.最后成功的和ceo进行了一番交流
如果在传达的时候中间一个环节忘记传递了,policy就不知道ceo在找他,ceo等了好久不来ceo就生气报错了
使用的时候需要注意: 有的同学,想在policy文件中导入versions就是直接使用import,在policy文件使用没有问题,很美,很高兴.但是在test.py执行的时候就会报错 因为我们在test.py中执行的import versions 相当于在test.py文件进行查找,肯定不会找到,我们需要在policy文件中向sys.path添加了当前的路劲就可以了 具体操作如下:
import os
import sys
sys.path.insert(os.path.dirname(__file__)
__file__获取的是当前文件的路径,这样我们就能在test中正常使用了,我们使用from也能够将某个包下所有的模块全都导入 比如我们现在想将cmd包下的所有的模块导入需要在bake包下的__init__.py进行设置
from . import *
我们需要在api包下设置__init__.py
__all__ = ["policy","versions"]
或
from . import policy
from . import versions
我们需要在db包下设置__init__.py
__all__ = ["models"]
或
from . import models
我们需要在cmd包下设置__init__.py
__all__ = ["manage"]
或
from . import manage
以上两种推荐使用下from . import manage 灵活,可读性高
test.py调用如下:
from bake.api import *
print(versions.name)
policy.get()
from bake.db import *
models.register_models(123)
from bake.cmd import *
print(manage.name)
在使用import有个注意点,python2中如果import包,没有__init__.py文件就会报错 python3 import没有__init__.py文件的包不会报错 from 包 import 包或者模块(在import后边不能在进行.操作)
路径: 绝对路径:从最外层(bake)包.查找的就是绝对路径 相对路径:.就是相对路径, ..是上一级目录 例如:我们在bake/api/version.py中想要导入bake/cmd/manage.py
# 绝对路径:
from bake.cmd import manage
manage.main()
#相对路径:
from ..cmd import manage
manage.main()
注意在使用相对路径的时候一定要在于bake同级的文件中测试 我们需要在和bake同级的test.py中测试
from bake.cmd import manage
logging日志模块
其实每个软件都是有错误日志的,开发人员可以通过错误日志中的内容对他的程序进行修改
这只是一种应用场景,有的还会将日志用于交易记录.比如你给我转账应该做记录吧,
我们使用的信用卡,每消费的一笔都会记录,我们来看看这个日志怎么用?
我们先来看一下函数式简单配置
import logging
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')
默认情况下Python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING
(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG),
默认的日志格式为日志级别:Logger名称:用户输出消息。
我们自己用函数写的这个可以正常使用但是不够灵活,我们看看这个灵活的
灵活配置日志级别,日志格式,输出位置:
import logging
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
datefmt='%a, %d %b %Y %H:%M:%S',
filename='/tmp/test.log',
filemode='w')
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')
basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:
filename:用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中。
filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
format:指定handler使用的日志显示格式。
datefmt:指定日期时间格式。
level:设置记录日志的级别
stream:用指定的stream创建StreamHandler。可以指定输出到
sys.stderr,sys.stdout或者文件(f=open(‘test.log’,’w’)),默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
format参数中可能用到的格式化串:
%(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用户输出的消息
logger对象配置
import logging
logger = logging.getLogger()
# 创建一个handler,用于写入日志文件
fh = logging.FileHandler('test.log',encoding='utf-8')
# 再创建一个handler,用于输出到控制台
ch = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setLevel(logging.DEBUG)
fh.setFormatter(formatter)
ch.setFormatter(formatter)
logger.addHandler(fh) #logger对象可以添加多个fh和ch对象
logger.addHandler(ch)
logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')
logging库提供了多个组件:Logger、Handler、Filter、Formatter。Logger对象提供应用程序可直接使用的接口,Handler发送日志到适当的目的地,Filter提供了过滤日志信息的方法,Formatter指定日志显示格式。另外,可以通过:logger.setLevel(logging.Debug)设置级别,当然,也可以通过
fh.setLevel(logging.Debug)单对文件流设置某个级别。
================================================================
import logging
logger = logging.getLogger()
# 创建一个handler,用于写入日志文件
fh = logging.FileHandler('test.log',encoding='utf-8')
# 再创建一个handler,用于输出到控制台
ch = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setLevel(logging.DEBUG)
fh.setFormatter(formatter)
ch.setFormatter(formatter)
logger.addHandler(fh) #logger对象可以添加多个fh和ch对象
logger.addHandler(ch)
logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')
logging日志旗舰版
"""
logging配置
"""
import os
import logging.config
# 定义三种日志输出格式 开始
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]'
'[%(levelname)s][%(message)s]' #其中name为getlogger指定的名字
simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'
# 定义日志输出格式 结束
logfile_dir = os.path.dirname(os.path.abspath(__file__)) # log文件的目录
logfile_name = 'all2.log' # log文件名
# 如果不存在定义的日志目录就创建一个
if not os.path.isdir(logfile_dir):
os.mkdir(logfile_dir)
# log文件的全路径
logfile_path = os.path.join(logfile_dir, logfile_name)
# log配置字典
LOGGING_DIC = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': standard_format
},
'simple': {
'format': simple_format
},
},
'filters': {},
'handlers': {
#打印到终端的日志
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler', # 打印到屏幕
'formatter': 'simple'
},
#打印到文件的日志,收集info及以上的日志
'default': {
'level': 'DEBUG',
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件
'formatter': 'standard',
'filename': logfile_path, # 日志文件
'maxBytes': 1024*1024*5, # 日志大小 5M
'backupCount': 5,
'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了
},
},
'loggers': {
#logging.getLogger(__name__)拿到的logger配置
'': {
'handlers': ['default', 'console'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
'level': 'DEBUG',
'propagate': True, # 向上(更高level的logger)传递
},
},
}
def load_my_logging_cfg():
logging.config.dictConfig(LOGGING_DIC) # 导入上面定义的logging配置
logger = logging.getLogger(__name__) # 生成一个log实例
logger.info('It works!') # 记录该文件的运行状态
if __name__ == '__main__':
load_my_logging_cfg()