一、time模块
在Python中,通常有这几种方式来表示时间:
- 时间戳(timestamp) :通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。
- 格式化的时间字符串
- 元组(struct_time) :struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天,夏令时)
时间转化表 如图显示:
-
import time
-
-
-
#time.sleep(5)
-
print(
"睡眠5s")
-
#sleep() #线程推迟自定的时间运行,单位为秒
-
-
#clock()
-
#这个需要注意啦,在不同的系统上含义不同,在unix系统上,它返回的是'进程时间',用秒表示的浮点数(时间戳)
-
#在windows中,第一次调用,返回的是进程运行的实际时间,而第二次之后的调用是自第一次调用后到现在的运行
-
#的时间,即两次的时间差
-
-
-
# 返回当前时间的时间戳(以秒计算,从1970年1月1日00:00:00开始到现在的时间差)
-
print(time.time())
# 结果:1537428578.9319177
-
-
# 将一个时间戳转换为当前时区
-
t = time.localtime()
-
print(t)
-
# 结果time.struct_time(tm_year=2018, tm_mon=9, tm_mday=20, tm_hour=15, tm_min=33, tm_sec=9, tm_wday=3, tm_yday=263, tm_isdst=0)
-
year = t.tm_year
-
month = t.tm_mon
-
print(year)
#2018
-
-
#gmtime()方法是将一个时间戳转换为UTC时区(0时区)的struct_time。
-
print(time.gmtime())
-
# 结果time.struct_time(tm_year=2018, tm_mon=9, tm_mday=20, tm_hour=7, tm_min=37, tm_sec=46, tm_wday=3, tm_yday=263, tm_isdst=0)
-
-
-
#返回utc时间的struc时间对象格式
-
print(time.gmtime(time.time()
-9000))
-
# 结果time.struct_time(tm_year=2018, tm_mon=9, tm_mday=20, tm_hour=5, tm_min=17, tm_sec=10, tm_wday=3, tm_yday=263, tm_isdst=0)
-
-
#-------将结构化时间转换时间戳
-
print(time.mktime(time.localtime()))
# 结果1537429976.0
-
-
-
# -----将结构化时间转换Fomart格式的字符串时间
-
print(time.strftime(
"%Y-%m-%d %X",time.localtime()))
#结果 2018-09-20 15:58:28
-
-
# --将字符串时间转化结构化时间
-
print(time.strptime(
"2016:12:26:12:34:33",
"%Y:%m:%d:%X"))
-
#结果time.struct_time(tm_year=2016, tm_mon=12, tm_mday=26, tm_hour=12, tm_min=34, tm_sec=33, tm_wday=0, tm_yday=361, tm_isdst=-1)
-
-
# 直接看时间
-
print(time.asctime())
#Thu Sep 20 16:04:16 2018 把结构换时间转换成固定的字符串表达式
-
print(time.ctime())
# Thu Sep 20 16:04:16 2018 把时间戳时间转换成固定的字符串表达式
-
-
-
datatime表示的一种时间
-
import datetime
-
-
#显示当前时间日期
-
print(datetime.datetime.now())
-
# 2018-09-20 16:10:36.019032
-
-
#当前时间+3天
-
print(datetime.datetime.now() + datetime.timedelta(
3))
-
#2018-09-23 16:10:36.020031
-
-
#当前时间-3天
-
print(datetime.datetime.now() + datetime.timedelta(
-3))
-
#2018-09-17 16:10:36.020031
-
-
#当前时间+30分
-
print(datetime.datetime.now() + datetime.timedelta(hours=
3))
-
#2018-09-20 19:10:36.020031
-
-
#时间替换
-
c_time = datetime.datetime.now()
-
print(c_time.replace(minute=
3,hour=
2))
-
#2018-09-20 16:10:36.019032 将小时数与分钟数替换 2018-09-20 02:03:36.020031
-
-
#时间戳直接转换为日期格式
-
print(datetime.date.fromtimestamp(time.time()))
# 2018-09-20
二 、random模块
随机生成内容
-
import random
-
-
#0,1之间时间生成的浮点数 float
-
print(random.random())
-
-
#随机生成传入参数范围内的数字 即 1,2,3
-
print(random.randint(
1,
3))
-
-
#随机生成传入参数范围内的数字,range顾头不顾尾
-
print(random.randrange(
1,
3))
-
-
#随机选择任意一个数字
-
print(random.choice([
1,
'23', [
4,
5]]))
-
-
#随机选择任意两个数字
-
print(random.sample([
1,
'23', [
4,
5]],
2))
随机生成一个验证码
-
#验证码
-
def v_code():
-
ret =
""
-
for i
in range(
5):
-
num = random.randint(
0,
9)
-
alf = chr(random.randint(
65,
122))
-
#字母与数字随机拼接
-
num_alf = str(random.choice([num,alf]))
-
ret +=num_alf
-
return ret
-
-
print(v_code())
三、sys模块
-
import sys
-
-
#命令行参数List,第一个元素是程序本身路径
-
print(sys.argv)
-
#结果['D:/Pycharm Community/python内置函数/sysTest.py']
-
-
#获取Python解释程序的版本信息
-
print(sys.version)
-
#结果3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:06:47) [MSC v.1914 32 bit (Intel)]
-
-
#最大的Int值
-
#print(sys.maxint)
-
-
#返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值(临时修改,不会保存)
-
print(sys.path)
-
#结果['D:\\Pycharm Community\\python内置函数', 'D:\\Pycharm Community\\python内置函数', 'C:\\Users\\Songyu.Ji\\venv\\python内置函数\\Scripts\\python37.zip', 'C:\\Users\\Songyu.Ji\\AppData\\Local\\Programs\\Python\\Python37-32\\DLLs', 'C:\\Users\\Songyu.Ji\\AppData\\Local\\Programs\\Python\\Python37-32\\lib', 'C:\\Users\\Songyu.Ji\\AppData\\Local\\Programs\\Python\\Python37-32', 'C:\\Users\\Songyu.Ji\\venv\\python内置函数', 'C:\\Users\\Songyu.Ji\\venv\\python内置函数\\lib\\site-packages', 'C:\\Users\\Songyu.Ji\\venv\\python内置函数\\lib\\site-packages\\setuptools-39.0.1-py3.7.egg', 'C:\\Users\\Songyu.Ji\\venv\\python内置函数\\lib\\site-packages\\pip-9.0.3-py3.7.egg']
-
-
#返回操作系统平台名称
-
print(sys.platform)
#win32
-
-
#退出程序,正常退出时exit(0)
-
print(sys.exit(
0))
四、os模块
os模块是与操作系统交互的一个接口
-
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
-
os.chdir(
"dirname") 改变当前脚本工作目录;相当于shell下cd
-
os.curdir 返回当前目录: (
'.')
-
os.pardir 获取当前目录的父目录字符串名:(
'..')
-
os.makedirs(
'dirname1/dirname2') 可生成多层递归目录
-
os.removedirs(
'dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
-
os.mkdir(
'dirname') 生成单级目录;相当于shell中mkdir dirname
-
os.rmdir(
'dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
-
os.listdir(
'dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
-
os.remove() 删除一个文件
-
os.rename(
"oldname",
"newname") 重命名文件/目录
-
os.stat(
'path/filename') 获取文件/目录信息
-
os.sep 输出操作系统特定的路径分隔符,win下为
"\\",Linux下为
"/"
-
os.linesep 输出当前平台使用的行终止符,win下为
"\t\n",Linux下为
"\n"
-
os.pathsep 输出用于分割文件路径的字符串 win下为;,Linux下为:
-
os.name 输出字符串指示当前使用平台。win->
'nt'; Linux->
'posix'
-
os.system(
"bash command") 运行shell命令,直接显示
-
os.environ 获取系统环境变量
-
os.path.abspath(path) 返回path规范化的绝对路径
-
os.path.split(path) 将path分割成目录和文件名二元组返回
-
os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素
-
os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
-
os.path.exists(path) 如果path存在,返回
True;如果path不存在,返回
False
-
os.path.isabs(path) 如果path是绝对路径,返回
True
-
os.path.isfile(path) 如果path是一个存在的文件,返回
True。否则返回
False
-
os.path.isdir(path) 如果path是一个存在的目录,则返回
True。否则返回
False
-
os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
-
os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间
-
os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间
五、json模块
之前我们学习过用eval内置方法可以将一个字符串转成python对象,不过,eval方法是有局限性的,对于普通的数据类型,json.loads和eval都能用,但遇到特殊类型的时候,eval就不管用了,所以eval的重点还是通常用来执行一个字符串表达式,并返回表达式的值。
-
import json
-
-
-
x=
"[null,true,false,1]"
-
#print(eval(x))
-
print(json.loads(x))
什么是序列化?
我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。
序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。
反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
-
# ----------------------------序列化
-
import json
-
-
dic = {
'name':
'alvin',
'age':
23,
'sex':
'male'}
-
print(type(dic))
# <class 'dict'>
-
-
j = json.dumps(dic)
-
print(type(j))
# <class 'str'>
-
-
f = open(
'序列化对象',
'w')
-
f.write(j)
# -------------------等价于json.dump(dic,f)
-
f.close()
-
-
# -----------------------------反序列化<br>
-
import json
-
-
f = open(
'序列化对象')
-
data = json.loads(f.read())
# 等价于data=json.load(f)
json
json 字符串必须用双引号
如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
JSON表示的对象就是标准的JavaScript语言的对象,JSON和Python内置的数据类型对应如下:
-
import json
-
-
#dct="{'1':111}"#json 不认单引号
-
#dct=str({"1":111})#报错,因为生成的数据还是单引号:{'one': 1}
-
-
dct=
'{"1":"111"}'
-
print(json.loads(dct))
-
-
#conclusion:
-
#无论数据是怎样创建的,只要满足json格式,就可以json.loads出来,不一定非要dumps的数据才能loads
-
-
-
-
-
dic = {
"name":
"rxz",
"age":
29,
"sex":
"gils"}
-
# json.dumps参数可以是字典,字符串,元组,整型,列表
-
data_str = json.dumps(dic)
#=====>h把dic变成字符创格式
-
print(type(data_str))
#<class 'str'>
-
print(data_str)
#{"name": "rxz", "age": 29, "sex": "gils"}
-
f = open(
"new_hello",
"w")
-
f.write(data_str)
-
f.flush()
-
f.close()
-
-
f_read = open(
"new_hello",
"r")
-
data = json.loads(f_read.read())
# 把数据取出来变成原来的格式
-
print(type(data))
#<class 'dict'>
-
print(data)
#{'name': 'rxz', 'age': 29, 'sex': 'gils'}
python中json.dump() 和 json.dumps() 有那些区别
下面演示如何将一个Python数据结构转换为JSON:
-
import json
-
-
-
dic = {
"name":
"rxz",
"age":
29,
"sex":
"gils"}
-
data_str = json.dumps(dic)
下面演示如何将一个JSON编码的字符串转换回一个Python数据结构:
-
import json
-
-
-
data = json.loads(json_str)
如果你要处理的是文件而不是字符串,你可以使用 json.dump() 和 json.load() 来编码和解码JSON数据。例如:
-
import json
-
-
-
# Writing JSON data
-
with open(
'data.json',
'w')
as f:
-
json.dump(data, f)
-
-
# Reading data back
-
with open(
'data.json',
'r')
as f:
-
data = json.load(f)
六、pickle模块
pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python,并且可能不同版本的Python彼此
都不兼容,因此,只能用pickle保存那些不重要的数据,不能成功地反序列化也没关系
-
##----------------------------序列化
-
import pickle
-
-
dic = {
"name":
"rxz",
"age":
29,
"sex":
"gils"}
-
-
print(type(dic))
#<class 'dict'>
-
-
j=pickle.dumps(dic)
-
print(type(j))
#<class 'bytes'>
-
-
-
f=open(
'序列化对象_pickle',
'wb')
#注意是w是写入str,wb是写入bytes,j是'bytes'
-
f.write(j)
#-------------------等价于pickle.dump(dic,f)
-
-
f.close()
-
#-------------------------反序列化
-
import pickle
-
f=open(
'序列化对象_pickle',
'rb')
-
-
data=pickle.loads(f.read())
# 等价于data=pickle.load(f)
-
-
-
print(data[
'age'])
七、shelve模块
shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写;key必须为字符串,而值可以是python所支持的数据类型
-
import shelve
-
-
f = shelve.open(
r'shelve) # 目的:将一个字典放入文本中
-
-
f['stu1_info
']={'name
':'rxz
','age
':'
29
'}
-
f['stu2_info
']={'name
':'gsh
','age
':'
3
'}
-
f['school_info
']={'website
':'tongcheng.com
','city
':'suzho
u'}
-
-
-
f.close()
-
-
print(f.get('stu_info
')['age
'])
八、xml模块
xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,古时候,在json还没诞生的黑暗年代,大家只能选择用xml呀,至今很多传统公司如金融行业的很多系统的接口还主要是xml。
xml的格式如下,就是通过<>节点来区别数据结构的:
-
<?xml version="1.0"?>
-
<data>
-
<country name="Liechtenstein">
-
<rank updated="yes">2
</rank>
-
<year>2008
</year>
-
<gdppc>141100
</gdppc>
-
<neighbor name="Austria" direction="E"/>
-
<neighbor name="Switzerland" direction="W"/>
-
</country>
-
<country name="Singapore">
-
<rank updated="yes">5
</rank>
-
<year>2011
</year>
-
<gdppc>59900
</gdppc>
-
<neighbor name="Malaysia" direction="N"/>
-
</country>
-
<country name="Panama">
-
<rank updated="yes">69
</rank>
-
<year>2011
</year>
-
<gdppc>13600
</gdppc>
-
<neighbor name="Costa Rica" direction="W"/>
-
<neighbor name="Colombia" direction="E"/>
-
</country>
-
</data>
-
-
xml数据
xml协议在各个语言里的都 是支持的,在python中可以用以下模块操作xml:
-
import xml.etree.ElementTree
as ET
-
-
tree = ET.parse(
"xmltest.xml")
-
root = tree.getroot()
-
print(root.tag)
-
-
#遍历xml文档
-
for child
in root:
-
print(child.tag, child.attrib)
-
for i
in child:
-
print(i.tag,i.text)
-
-
#只遍历year 节点
-
for node
in root.iter(
'year'):
-
print(node.tag,node.text)
-
#---------------------------------------
-
-
import xml.etree.ElementTree
as ET
-
-
tree = ET.parse(
"xmltest.xml")
-
root = tree.getroot()
-
-
#修改
-
for node
in root.iter(
'year'):
-
new_year = int(node.text) +
1
-
node.text = str(new_year)
-
node.set(
"updated",
"yes")
-
-
tree.write(
"xmltest.xml")
-
-
-
#删除node
-
for country
in root.findall(
'country'):
-
rank = int(country.find(
'rank').text)
-
if rank >
50:
-
root.remove(country)
-
-
tree.write(
'output.xml')
自己创建xml文档:
-
import xml.etree.ElementTree
as ET
-
-
-
new_xml = ET.Element(
"namelist")
-
name = ET.SubElement(new_xml,
"name",attrib={
"enrolled":
"yes"})
-
age = ET.SubElement(name,
"age",attrib={
"checked":
"no"})
-
sex = ET.SubElement(name,
"sex")
-
sex.text =
'33'
-
name2 = ET.SubElement(new_xml,
"name",attrib={
"enrolled":
"no"})
-
age = ET.SubElement(name2,
"age")
-
age.text =
'19'
-
-
et = ET.ElementTree(new_xml)
#生成文档对象
-
et.write(
"test.xml", encoding=
"utf-8",xml_declaration=
True)
-
-
ET.dump(new_xml)
#打印生成的格式
-
九、re模块
就其本质而言,正则表达式(或 RE)是一种小型的、高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。
字符匹配(普通字符,元字符):
1 普通字符:大多数字符和字母都会和自身匹配
>>> re.findall('alvin','yuanaleSxalexwupeiqi')
['alvin']
2 元字符:. ^ $ * + ? { } [ ] | ( ) \
-
import re
-
-
# . 就是通配符,一个点代表一个字符
-
s = re.findall(
"a...x",
"adsfaeyuxslg")
-
print(s)
# ['aeyux']
-
-
# ^ 这个代表以什么开头
-
s = re.findall(
"^a..x",
"adsfaeyuxslg")
-
print(s)
# ['']
-
-
s = re.findall(
"a..x",
"adsxaeyxslg")
-
print(s)
# ['adsx', 'aeyx']
-
-
-
# $ 以什么结尾的
-
s = re.findall(
"a..x$",
"adsxaeyxslg")
-
print(s)
#[]
-
a = re.findall(
"a..x$",
"adsxaeyxslgarrx")
-
print(a)
#['arrx']
-
-
# 重复符号有4个,第一个(* )代表0到无穷次,贪婪匹配
-
s = re.findall(
"d*",
"sfdderddddddyuyygdd")
-
print(s)
#['', '', 'dd', '', '', 'dddddd', '', '', '', '', '', 'dd', '']
-
# 重复符号有4个,第二个(+ )代表1 到无穷次,贪婪匹配
-
s = re.findall(
"alex+",
"asdhfalexxx")
-
print(s)
#['alexxx']
-
s = re.findall(
"alex*",
"asdhfalexxx")
-
print(s)
#['alexxx']
-
-
a = re.findall(
"alex+",
"asdhfale")
-
print(a)
#[]
-
a = re.findall(
"alex*",
"asdhfale")
-
print(a)
#['ale']
-
-
# 重复符号有4个,第三个(?)代表0 到1
-
s = re.findall(
"alex?",
"asdhfalexxx")
-
print(s)
#['alex']
-
s = re.findall(
"alex?",
"asdhfale")
-
print(s)
#['ale']
-
-
# 重复符号有4个,第四个({})代表0 到你想到取得次数
-
"""
-
{0,}=====>*
-
{1,}=====>+
-
{0,1}=====>?
-
{6}=====>重复6次
-
{1,6}=====>重复,1,2,3,4,5,6其中任何一次
-
"""
-
s = re.findall(
"alex{6}",
"asdhfalexxxxxx")
-
print(s)
#['alexxxxxx']
-
s = re.findall(
"alex{0,6}",
"asdhfalexx")
-
print(s)
#['alexx']
元字符之. ^ $ * + ? { }
-
import re
-
-
ret=re.findall(
'a..in',
'helloalvin')
-
print(ret)
#['alvin']
-
-
-
ret=re.findall(
'^a...n',
'alvinhelloawwwn')
-
print(ret)
#['alvin']
-
-
-
ret=re.findall(
'a...n$',
'alvinhelloawwwn')
-
print(ret)
#['awwwn']
-
-
-
ret=re.findall(
'a...n$',
'alvinhelloawwwn')
-
print(ret)
#['awwwn']
-
-
-
ret=re.findall(
'abc*',
'abcccc')
#贪婪匹配[0,+oo]
-
print(ret)
#['abcccc']
-
-
ret=re.findall(
'abc+',
'abccc')
#[1,+oo]
-
print(ret)
#['abccc']
-
-
ret=re.findall(
'abc?',
'abccc')
#[0,1]
-
print(ret)
#['abc']
-
-
-
ret=re.findall(
'abc{1,4}',
'abccc')
-
print(ret)
#['abccc'] 贪婪匹配
注意:前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配
-
#--------------------------------------------字符集[]
-
ret=re.findall(
'a[bc]d',
'acd')
-
print(ret)
#['acd']
-
-
ret=re.findall(
'[a-z]',
'acd')
-
print(ret)
#['a', 'c', 'd']
-
-
ret=re.findall(
'[.*+]',
'a.cd+')
-
print(ret)
#['.', '+']
-
-
#在字符集里有功能的符号: - ^ \
-
-
ret=re.findall(
'[1-9]',
'45dha3')
-
print(ret)
#['4', '5', '3']
-
-
ret=re.findall(
'[^ab]',
'45bdha3')
-
print(ret)
#['4', '5', 'd', 'h', '3']
-
-
ret=re.findall(
'[\d]',
'45bdha3')
-
print(ret)
#['4', '5', '3']
元字符之转义符\
反斜杠后边跟元字符去除特殊功能,比如\.
反斜杠后边跟普通字符实现特殊功能,比如\d
\d 匹配任何十进制数;它相当于类 [0-9]。
\D 匹配任何非数字字符;它相当于类 [^0-9]。
\s 匹配任何空白字符;它相当于类 [ \t\n\r\f\v]。
\S 匹配任何非空白字符;它相当于类 [^ \t\n\r\f\v]。
\w 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]。
\W 匹配任何非字母数字字符;它相当于类 [^a-zA-Z0-9_]
\b 匹配一个特殊字符边界,比如空格 ,&,#等
-
import re
-
-
ret=re.findall(
'I\b',
'I am LIST')
-
print(ret)
#[]
-
ret=re.findall(
r'I\b',
'I am LIST')
-
print(ret)
#['I']
现在我们聊一聊\,先看下面两个匹配:
-
#-----------------------------eg1:
-
import re
-
ret=re.findall(
'c\l',
'abc\le')
-
print(ret)
#[]
-
ret=re.findall(
'c\\l',
'abc\le')
-
print(ret)
#[]
-
ret=re.findall(
'c\\\\l',
'abc\le')
-
print(ret)
#['c\\l']
-
ret=re.findall(
r'c\\l',
'abc\le')
-
print(ret)
#['c\\l']
-
-
#-----------------------------eg2:
-
#之所以选择\b是因为\b在ASCII表中是有意义的
-
m = re.findall(
'\bblow',
'blow')
-
print(m)
-
m = re.findall(
r'\bblow',
'blow')
-
print(m)
元字符之分组()
-
import re
-
-
-
m = re.findall(
r'(ad)+',
'add')
-
print(m)
-
-
ret=re.search(
'(?P<id>\d{2})/(?P<name>\w{3})',
'23/com')
-
print(ret.group())
#23/com
-
print(ret.group(
'id'))
#23
元字符之|
-
import re
-
-
ret = re.findall(
r"kr|z",
"sdfkrsf")
-
print(ret)
#['kr']
-
ret = re.findall(
r"kr|z",
"sdfkrzsf")
-
print(ret)
#['kr', 'z']
-
import re
-
-
ret=re.search(
'(ab)|\d',
'rabhdg8sd')
-
print(ret.group())
#ab
re模块下的常用方法
-
import re
-
#1
-
re.findall(
'a',
'alvin yuan')
#返回所有满足匹配条件的结果,放在列表里
-
#2
-
re.search(
'a',
'alvin yuan').group()
#函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以
-
# 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
-
-
#3
-
re.match(
'a',
'abc').group()
#同search,不过尽在字符串开始处进行匹配
-
-
#4
-
ret=re.split(
'[ab]',
'abcd')
#先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割
-
print(ret)
#['', '', 'cd']
-
-
#5
-
ret=re.sub(
'\d',
'abc',
'alvin5yuan6',
1)
-
print(ret)
#alvinabcyuan6
-
ret=re.subn(
'\d',
'abc',
'alvin5yuan6')
-
print(ret)
#('alvinabcyuanabc', 2)
-
-
#6
-
obj=re.compile(
'\d{3}')
-
ret=obj.search(
'abc123eeee')
-
print(ret.group())
#123
-
-
-
import re
-
ret=re.finditer(
'\d',
'ds3sy4784a')
-
print(ret)
#<callable_iterator object at 0x10195f940>
-
-
print(next(ret).group())
-
print(next(ret).group())
注意:
-
import re
-
-
ret=re.findall(
'www.(baidu|oldboy).com',
'www.oldboy.com')
-
print(ret)
#['oldboy'] 这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可
-
-
ret=re.findall(
'www.(?:baidu|oldboy).com',
'www.oldboy.com')
-
print(ret)
#['www.oldboy.com']
-
import re
-
-
print(re.findall(
"<(?P<tag_name>\w+)>\w+</(?P=tag_name)>",
"<h1>hello</h1>"))
-
print(re.search(
"<(?P<tag_name>\w+)>\w+</(?P=tag_name)>",
"<h1>hello</h1>"))
-
print(re.search(
r"<(\w+)>\w+</\1>",
"<h1>hello</h1>"))
-
#匹配出所有的整数
-
import re
-
-
#ret=re.findall(r"\d+{0}]","1-2*(60+(-40.35/5)-(-4*3))")
-
ret=re.findall(
r"-?\d+\.\d*|(-?\d+)",
"1-2*(60+(-40.35/5)-(-4*3))")
-
ret.remove(
"")
-
-
print(ret)
十、logging模块
-
import logging
-
-
logging.debug(
'debug message')
-
logging.info(
'info message')
-
logging.warning(
'warning message')
-
logging.error(
'error message')
-
logging.critical(
'critical message')
-
-
"""
-
WARNING:root:warning message
-
ERROR:root:error message
-
CRITICAL:root:critical message
-
"""
可见,默认情况下Python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET),默认的日志格式为日志级别:Logger名称:用户输出消息。
2、灵活配置日志级别,日志格式,输出位置
-
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')
-
查看输出:
cat /tmp/test.log
Mon, 05 May 2018 16:29:53 test_logging.py[line:9] DEBUG debug message
Mon, 05 May 2018 16:29:53 test_logging.py[line:10] INFO info message
Mon, 05 May 2018 16:29:53 test_logging.py[line:11] WARNING warning message
Mon, 05 May 2018 16:29:53 test_logging.py[line:12] ERROR error message
Mon, 05 May 2018 16:29:53 test_logging.py[line:13] CRITICAL critical message
可见在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有
filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
format:指定handler使用的日志显示格式。
datefmt:指定日期时间格式。
level:设置rootlogger(后边会讲解具体概念)的日志级别
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用户输出的消息
3、logger对象
上述几个例子中我们了解到了logging.debug()、logging.info()、logging.warning()、logging.error()、logging.critical()(分别用以记录不同级别的日志信息),logging.basicConfig()(用默认日志格式(Formatter)为日志系统建立一个默认的流处理器(StreamHandler),设置基础配置(如日志级别等)并加到root logger(根Logger)中)这几个logging模块级别的函数,另外还有一个模块级别的函数是logging.getLogger([name])(返回一个logger对象,如果没有指定名字将返回root logger)
先看一个最简单的过程:
-
import logging
-
-
logger = logging.getLogger()
-
# 创建一个handler,用于写入日志文件
-
fh = logging.FileHandler(
'test.log')
-
-
# 再创建一个handler,用于输出到控制台
-
ch = logging.StreamHandler()
-
-
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s')
-
-
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指定日志显示格式。
(1)
Logger是一个树形层级结构,输出信息之前都要获得一个Logger(如果没有显示的获取则自动创建并使用root Logger,如第一个例子所示)。
logger = logging.getLogger()返回一个默认的Logger也即root Logger,并应用默认的日志级别、Handler和Formatter设置。
当然也可以通过Logger.setLevel(lel)指定最低的日志级别,可用的日志级别有logging.DEBUG、logging.INFO、logging.WARNING、logging.ERROR、logging.CRITICAL。
Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical()输出不同级别的日志,只有日志等级大于或等于设置的日志级别的日志才会被输出。
-
import logging
-
-
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')
-
只输出了
2018-09-25 12:54:43,222 - root - WARNING - logger warning message
2018-09-25 12:54:43,223 - root - ERROR - logger error message
2018-09-25 12:54:43,224 - root - CRITICAL - logger critical message
从这个输出可以看出logger = logging.getLogger()返回的Logger名为root。这里没有用logger.setLevel(logging.Debug)显示的为logger设置日志级别,所以使用默认的日志级别WARNIING,故结果只输出了大于等于WARNIING级别的信息。
(2) 如果我们再创建两个logger对象:
-
import logging
-
##################################################
-
logger1 = logging.getLogger(
'mylogger')
-
logger1.setLevel(logging.DEBUG)
-
-
logger2 = logging.getLogger(
'mylogger')
-
logger2.setLevel(logging.INFO)
-
-
logger1.addHandler(fh)
-
logger1.addHandler(ch)
-
-
logger2.addHandler(fh)
-
logger2.addHandler(ch)
-
-
logger1.debug(
'logger1 debug message')
-
logger1.info(
'logger1 info message')
-
logger1.warning(
'logger1 warning message')
-
logger1.error(
'logger1 error message')
-
logger1.critical(
'logger1 critical message')
-
-
logger2.debug(
'logger2 debug message')
-
logger2.info(
'logger2 info message')
-
logger2.warning(
'logger2 warning message')
-
logger2.error(
'logger2 error message')
-
logger2.critical(
'logger2 critical message')
-
结果:
这里有两个个问题:
<1>我们明明通过logger1.setLevel(logging.DEBUG)将logger1的日志级别设置为了DEBUG,为何显示的时候没有显示出DEBUG级别的日志信息,而是从INFO级别的日志开始显示呢?
原来logger1和logger2对应的是同一个Logger实例,只要logging.getLogger(name)中名称参数name相同则返回的Logger实例就是同一个,且仅有一个,也即name与Logger实例一一对应。在logger2实例中通过logger2.setLevel(logging.INFO)设置mylogger的日志级别为logging.INFO,所以最后logger1的输出遵从了后来设置的日志级别。
<2>为什么logger1、logger2对应的每个输出分别显示两次?
这是因为我们通过logger = logging.getLogger()显示的创建了root Logger,而logger1 = logging.getLogger('mylogger')创建了root Logger的孩子(root.)mylogger,logger2同样。而孩子,孙子,重孙……既会将消息分发给他的handler进行处理也会传递给所有的祖先Logger处理。
ok,那么现在我们把
# logger.addHandler(fh)
# logger.addHandler(ch) 注释掉,我们再来看效果:
因为我们注释了logger对象显示的位置,所以才用了默认方式,即标准输出方式。因为它的父级没有设置文件显示方式,所以在这里只打印了一次。
孩子,孙子,重孙……可逐层继承来自祖先的日志级别、Handler、Filter设置,也可以通过Logger.setLevel(lel)、Logger.addHandler(hdlr)、Logger.removeHandler(hdlr)、Logger.addFilter(filt)、Logger.removeFilter(filt)。设置自己特别的日志级别、Handler、Filter。若不设置则使用继承来的值。
<3>Filter
限制只有满足过滤规则的日志才会输出。
比如我们定义了filter = logging.Filter('a.b.c'),并将这个Filter添加到了一个Handler上,则使用该Handler的Logger中只有名字带 a.b.c前缀的Logger才能输出其日志。
filter = logging.Filter('mylogger')
logger.addFilter(filter)
这是只对logger这个对象进行筛选
如果想对所有的对象进行筛选,则:
filter = logging.Filter('mylogger')
fh.addFilter(filter)
ch.addFilter(filter)
这样,所有添加fh或者ch的logger对象都会进行筛选。
-
import logging
-
##################################################
-
logger1 = logging.getLogger(
'mylogger')
-
logger1.setLevel(logging.DEBUG)
-
-
logger2 = logging.getLogger(
'mylogger')
-
logger2.setLevel(logging.INFO)
-
-
logger1.addHandler(fh)
-
logger1.addHandler(ch)
-
-
logger2.addHandler(fh)
-
logger2.addHandler(ch)
-
-
logger1.debug(
'logger1 debug message')
-
logger1.info(
'logger1 info message')
-
logger1.warning(
'logger1 warning message')
-
logger1.error(
'logger1 error message')
-
logger1.critical(
'logger1 critical message')
-
-
logger2.debug(
'logger2 debug message')
-
logger2.info(
'logger2 info message')
-
logger2.warning(
'logger2 warning message')
-
logger2.error(
'logger2 error message')
-
logger2.critical(
'logger2 critical message')
-
-
#coding:utf-8
-
import logging
-
-
# 创建一个logger
-
logger = logging.getLogger()
-
-
logger1 = logging.getLogger(
'mylogger')
-
logger1.setLevel(logging.DEBUG)
-
-
logger2 = logging.getLogger(
'mylogger')
-
logger2.setLevel(logging.INFO)
-
-
logger3 = logging.getLogger(
'mylogger.child1')
-
logger3.setLevel(logging.WARNING)
-
-
logger4 = logging.getLogger(
'mylogger.child1.child2')
-
logger4.setLevel(logging.DEBUG)
-
-
logger5 = logging.getLogger(
'mylogger.child1.child2.child3')
-
logger5.setLevel(logging.DEBUG)
-
-
# 创建一个handler,用于写入日志文件
-
fh = logging.FileHandler(
'/tmp/test.log')
-
-
# 再创建一个handler,用于输出到控制台
-
ch = logging.StreamHandler()
-
-
# 定义handler的输出格式formatter
-
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s')
-
fh.setFormatter(formatter)
-
ch.setFormatter(formatter)
-
-
#定义一个filter
-
#filter = logging.Filter('mylogger.child1.child2')
-
#fh.addFilter(filter)
-
-
# 给logger添加handler
-
#logger.addFilter(filter)
-
logger.addHandler(fh)
-
logger.addHandler(ch)
-
-
#logger1.addFilter(filter)
-
logger1.addHandler(fh)
-
logger1.addHandler(ch)
-
-
logger2.addHandler(fh)
-
logger2.addHandler(ch)
-
-
#logger3.addFilter(filter)
-
logger3.addHandler(fh)
-
logger3.addHandler(ch)
-
-
#logger4.addFilter(filter)
-
logger4.addHandler(fh)
-
logger4.addHandler(ch)
-
-
logger5.addHandler(fh)
-
logger5.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')
-
-
logger1.debug(
'logger1 debug message')
-
logger1.info(
'logger1 info message')
-
logger1.warning(
'logger1 warning message')
-
logger1.error(
'logger1 error message')
-
logger1.critical(
'logger1 critical message')
-
-
logger2.debug(
'logger2 debug message')
-
logger2.info(
'logger2 info message')
-
logger2.warning(
'logger2 warning message')
-
logger2.error(
'logger2 error message')
-
logger2.critical(
'logger2 critical message')
-
-
logger3.debug(
'logger3 debug message')
-
logger3.info(
'logger3 info message')
-
logger3.warning(
'logger3 warning message')
-
logger3.error(
'logger3 error message')
-
logger3.critical(
'logger3 critical message')
-
-
logger4.debug(
'logger4 debug message')
-
logger4.info(
'logger4 info message')
-
logger4.warning(
'logger4 warning message')
-
logger4.error(
'logger4 error message')
-
logger4.critical(
'logger4 critical message')
-
-
logger5.debug(
'logger5 debug message')
-
logger5.info(
'logger5 info message')
-
logger5.warning(
'logger5 warning message')
-
logger5.error(
'logger5 error message')
-
logger5.critical(
'logger5 critical message')
应用
-
import os
-
import time
-
import logging
-
from config
import settings
-
-
-
def get_logger(card_num, struct_time):
-
-
if struct_time.tm_mday <
23:
-
file_name =
"%s_%s_%d" %(struct_time.tm_year, struct_time.tm_mon,
22)
-
else:
-
file_name =
"%s_%s_%d" %(struct_time.tm_year, struct_time.tm_mon+
1,
22)
-
-
file_handler = logging.FileHandler(
-
os.path.join(settings.USER_DIR_FOLDER, card_num,
'record', file_name),
-
encoding=
'utf-8'
-
)
-
fmt = logging.Formatter(fmt=
"%(asctime)s : %(message)s")
-
file_handler.setFormatter(fmt)
-
-
logger1 = logging.Logger(
'user_logger', level=logging.INFO)
-
logger1.addHandler(file_handler)
-
return logger1