6、python全栈之路-常用模块

六、常用模块

http://www.cnblogs.com/Eva-J/articles/7228075.html#_label10

•认识模块 •什么是模块

•模块的导入和使用

 

•常用模块一 •collections模块

•时间模块

random模块

os模块

sys模块

•序列化模块

re模块

 

•常用模块二 •hashlib模块

configparse模块

logging模块

1、认识模块

1.1 什么是模块

常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。

但其实import加载的模块分为四个通用类别: 

1 使用python编写的代码(.py文件)

2 已被编译为共享库或DLLCC++扩展

3 包好一组模块的包

4 使用C编写并链接到python解释器的内置模块

1.2 为何要使用模块

   如果你退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py被称为脚本script

 

    随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用

2collections模块

在内置数据类型(dictlistsettuple)的基础上,collections模块还提供了几个额外的数据类型:CounterdequedefaultdictnamedtupleOrderedDict等。

2.1 namedtuple

生成可以使用名字来访问元素内容的tuple我们知道tuple可以表示不变集合,例如,一个点的二维坐标就可以表示成:

>>> p = (1, 2)

但是,看到(1, 2),很难看出这个tuple是用来表示一个坐标的。

这时,namedtuple就派上了用场:

>>> from collections import namedtuple

>>> Point = namedtuple('Point', ['x', 'y'])

>>> p = Point(1, 2)

>>> p.x

1

>>> p.y

2

 

类似的,如果要用坐标和半径表示一个圆,也可以用namedtuple定义:

#namedtuple('名称', [属性list]):

Circle = namedtuple('Circle', ['x', 'y', 'r'])

2.2 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除了实现listappend()pop()外,还支持appendleft()popleft(),这样就可以非常高效地往头部添加或删除元素。

2.3 OrderedDict

有序字典

使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序。

如果要保持Key的顺序,可以用OrderedDict

>>> from collections import OrderedDict

>>> d = dict([('a', 1), ('b', 2), ('c', 3)])

>>> d # dictKey是无序的

{'a': 1, 'c': 3, 'b': 2}

>>> od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])

>>> od # OrderedDictKey是有序的

OrderedDict([('a', 1), ('b', 2), ('c', 3)])

 

注意,OrderedDictKey会按照插入的顺序排列,不是Key本身排序:

>>> od = OrderedDict()

>>> od['z'] = 1

>>> od['y'] = 2

>>> od['x'] = 3

>>> od.keys() # 按照插入的Key的顺序返回

['z', 'y', 'x']

2.4 defaultdict

带有默认值的字典

有如下值集合 [11,22,33,44,55,66,77,88,99,90...],将所有大于 66 的值保存至字典的第一个key中,将小于 66 的值保存至第二个key的值中。

 

原生字典解决方法

即: {'k1': 大于66 , 'k2': 小于66}

values = [11, 22, 33,44,55,66,77,88,99,90]

my_dict = {}

 

for value in  values:

    if value>66:

        if my_dict.has_key('k1'):

            my_dict['k1'].append(value)

        else:

            my_dict['k1'] = [value]

    else:

        if my_dict.has_key('k2'):

            my_dict['k2'].append(value)

        else:

            my_dict['k2'] = [value]

 

defaultdict字典解决方法

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'

>>> dd['key1'] # key1存在

'abc'

>>> dd['key2'] # key2不存在,返回默认值

'N/A'

2.5 Counter

计数器,主要用来计数

Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。计数值可以是任意的Interger(包括0和负数)。Counter类和其他语言的bagsmultisets很相似。

 

c = Counter('abcdeabcdabcaba')

print c

输出:Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1})

其他详细内容 http://www.cnblogs.com/Eva-J/articles/7291842.html

3、时间模块

和时间有关系的我们就要用到时间模块。在使用模块之前,应该首先导入这个模块。

3.1 常用方法

3.1.1 time.sleep(secs)

(线程)推迟指定的时间运行。单位为秒。

3.1.2 time.time()

获取当前时间戳

3.2 表示时间的三种方式

Python中,通常有这三种方式来表示时间:时间戳、元组(struct_time)、格式化的时间字符串:

3.2.1 时间戳(timestamp)

常来说,时间戳表示的是从19701100:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。

#时间戳

>>>time.time()

1500875844.800804

3.2.2 格式化的时间字符串(Format String)

#时间字符串

>>>time.strftime("%Y-%m-%d %X")

'2017-07-24 13:54:37'

>>>time.strftime("%Y-%m-%d %H-%M-%S")

'2017-07-24 13-55-04'

 

python中时间日期格式化符号:

%y 两位数的年份表示(00-99

%Y 四位数的年份表示(000-9999

%m 月份(01-12

%d 月内中的一天(0-31

%H 24小时制小时数(0-23

%I 12小时制小时数(01-12

%M 分钟数(00=59

%S 秒(00-59

%a 本地简化星期名称

%A 本地完整星期名称

%b 本地简化的月份名称

%B 本地完整的月份名称

%c 本地相应的日期表示和时间表示

%j 年内的一天(001-366

%p 本地A.M.P.M.的等价符

%U 一年中的星期数(00-53)星期天为星期的开始

%w 星期(0-6),星期天为星期的开始

%W 一年中的星期数(00-53)星期一为星期的开始

%x 本地相应的日期表示

%X 本地相应的时间表示

%Z 当前时区的名称

%% %号本身

3.2.3 元组(struct_time)

truct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天等)

 

#时间元组:localtime将一个时间戳转换为当前时区的struct_time

time.localtime()

time.struct_time(tm_year=2017, tm_mon=7, tm_mday=24,

              tm_hour=13, tm_min=59, tm_sec=37,

              tm_wday=0, tm_yday=205, tm_isdst=0)

 

3.2.4 小结

时间戳是计算机能够识别的时间;时间字符串是人能够看懂的时间;元组则是用来操作时间的

3.3 几种格式之间的转换

 

3.3.1 时间戳-->结构化时间

#time.gmtime(时间戳)    #UTC时间,与英国伦敦当地时间一致

#time.localtime(时间戳) #当地时间。例如我们现在在北京执行这个方法:与UTC时间相差8小时,UTC时间+8小时 = 北京时间

>>>time.gmtime(1500000000)

time.struct_time(tm_year=2017, tm_mon=7, tm_mday=14, tm_hour=2, tm_min=40, tm_sec=0, tm_wday=4, tm_yday=195, tm_isdst=0)

>>>time.localtime(1500000000)

time.struct_time(tm_year=2017, tm_mon=7, tm_mday=14, tm_hour=10, tm_min=40, tm_sec=0, tm_wday=4, tm_yday=195, tm_isdst=0)

3.3.2 结构化时间-->时间戳 

#time.mktime(结构化时间)

>>>time_tuple = time.localtime(1500000000)

>>>time.mktime(time_tuple)

1500000000.0

3.3.3 结构化时间-->字符串时间

#time.strftime("格式定义","结构化时间")  结构化时间参数若不传,则现实当前时间

>>>time.strftime("%Y-%m-%d %X")

'2017-07-24 14:55:36'

>>>time.strftime("%Y-%m-%d",time.localtime(1500000000))

'2017-07-14'

3.3.4 字符串时间-->结构化时间

#time.strptime(时间字符串,字符串对应格式)

>>>time.strptime("2017-03-16","%Y-%m-%d")

time.struct_time(tm_year=2017, tm_mon=3, tm_mday=16, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=75, tm_isdst=-1)

>>>time.strptime("07/24/2017","%m/%d/%Y")

time.struct_time(tm_year=2017, tm_mon=7, tm_mday=24, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=0, tm_yday=205, tm_isdst=-1)

3.3.5 结构化时间 --> %a %b %d %H:%M:%S %Y

 

#time.asctime(结构化时间) 如果不传参数,直接返回当前时间的格式化串

>>>time.asctime(time.localtime(1500000000))

'Fri Jul 14 10:40:00 2017'

>>>time.asctime()

'Mon Jul 24 15:18:33 2017'

3.3.6 %a %d %d %H:%M:%S %Y--> 结构化时间

#time.ctime(时间戳)  如果不传参数,直接返回当前时间的格式化串

>>>time.ctime()

'Mon Jul 24 15:19:07 2017'

>>>time.ctime(1500000000)

'Fri Jul 14 10:40:00 2017'

3.4 实例:计算时间差

import time

true_time=time.mktime(time.strptime('2017-09-11 08:30:00','%Y-%m-%d %H:%M:%S'))

time_now=time.mktime(time.strptime('2017-09-12 11:00:00','%Y-%m-%d %H:%M:%S'))

dif_time=time_now-true_time

struct_time=time.gmtime(dif_time)

print('过去了%d%d%d%d小时%d分钟%d'%(struct_time.tm_year-1970,struct_time.tm_mon-1,

                                       struct_time.tm_mday-1,struct_time.tm_hour,

                                       struct_time.tm_min,struct_time.tm_sec))

 

4random模块

>>> import random

4.1 随机小数

>>> random.random()      # 大于0且小于1之间的小数

0.7664338663654585

>>> random.uniform(1,3) #大于1小于3的小数

1.6270147180533838

4.2 随机整数

>>> random.randint(1,5)  # 大于等于1且小于等于5之间的整数

>>> random.randrange(1,10,2) # 大于等于1且小于10之间的奇数

4.3 随机选择一个返回

>>> random.choice([1,'23',[4,5]])  # #1或者23或者[4,5]

4.4 随机选择多个返回,返回的个数为函数的第二个参数

>>> random.sample([1,'23',[4,5]],2) # #列表元素任意2个组合

[[4, 5], '23']

4.5打乱列表顺序

>>> item=[1,3,5,7,9]

>>> random.shuffle(item) # 打乱次序

>>> item

[5, 1, 3, 7, 9]

>>> random.shuffle(item)

>>> item

[5, 9, 7, 1, 3]

4.6 实例:生成随机验证码

import random
li = []
for i in range(4):
    res = random.randint(0,9)
    res1 = chr(random.randint(65,90))
    res2 = chr(random.randint(97,122))
    val = random.choice([res,res1,res2])
    li.append(str(val))
print(''.join(li))

5os模块

os模块是与操作系统交互的一个接口

5.1 常用用法

os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径

os.chdir("dirname")  改变当前脚本工作目录;相当于shellcd

os.curdir  返回当前目录: ('.')

os.pardir  获取当前目录的父目录字符串名:('..')

os.makedirs('dirname1/dirname2')    可生成多层递归目录

os.removedirs('dirname1')    若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推

os.mkdir('dirname')    生成单级目录;相当于shellmkdir dirname

os.rmdir('dirname')    删除单级空目录,若目录不为空则无法删除,报错;相当于shellrmdir 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.popen("bash command)  运行shell命令,获取执行结果

os.environ  获取系统环境变量

 

os.path

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所指向的文件或者目录的最后修改时间

os.path.getsize(path) 返回path的大小

5.2 stat 结构:

注意:os.stat('path/filename')  获取文件/目录信息 的结构说明

st_mode: inode 保护模式

st_ino: inode 节点号。

st_dev: inode 驻留的设备。

st_nlink: inode 的链接数。

st_uid: 所有者的用户ID

st_gid: 所有者的组ID

st_size: 普通文件以字节为单位的大小;包含等待某些特殊文件的数据。

st_atime: 上次访问的时间。

st_mtime: 最后一次修改的时间。

st_ctime: 由操作系统报告的"ctime"。在某些系统上(如Unix)是最新的元数据更改的时间,在其它系统上(如Windows)是创建时间(详细信息参见平台的文档)。

6sys模块

sys模块是与python解释器交互的一个接口

6.1 常用用法

sys.argv           命令行参数List,第一个元素是程序本身路径

sys.exit(n)        退出程序,正常退出时exit(0)

sys.version        获取Python解释程序的版本信息

sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值

sys.platform       返回操作系统平台名称

6.2 实例:异常处理和status

import sys

try:

    sys.exit(1)

except SystemExit as e:

    print(e)

7、序列化模块

7.1 序列化

7.1.1什么叫序列化

将原本的字典、列表等内容转换成一个字符串的过程就叫做序列化。

7.1.2序列化的目的

1、以某种存储形式使自定义对象持久化;

2、将对象从一个地方传递到另一个地方。

3、使程序更具维护性。

7.2 json

Json模块提供了四个功能:dumpsdumploadsload

7.2.1 loadsdumps

import json

dic = {'k1':'v1','k2':'v2','k3':'v3'}

str_dic = json.dumps(dic)  #序列化:将一个字典转换成一个字符串

print(type(str_dic),str_dic)  #<class 'str'> {"k3": "v3", "k1": "v1", "k2": "v2"}

#注意,json转换完的字符串类型的字典中的字符串是由""表示的

 

dic2 = json.loads(str_dic)  #反序列化:将一个字符串格式的字典转换成一个字典

#注意,要用jsonloads功能处理的字符串类型的字典中的字符串必须由""表示

print(type(dic2),dic2)  #<class 'dict'> {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}

 

list_dic = [1,['a','b','c'],3,{'k1':'v1','k2':'v2'}]

str_dic = json.dumps(list_dic) #也可以处理嵌套的数据类型

print(type(str_dic),str_dic) #<class 'str'> [1, ["a", "b", "c"], 3, {"k1": "v1", "k2": "v2"}]

list_dic2 = json.loads(str_dic)

print(type(list_dic2),list_dic2) #<class 'list'> [1, ['a', 'b', 'c'], 3, {'k1': 'v1', 'k2': 'v2'}]

7.2.2 loaddump

import json

f = open('json_file','w')

dic = {'k1':'v1','k2':'v2','k3':'v3'}

json.dump(dic,f)  #dump方法接收一个文件句柄,直接将字典转换成json字符串写入文件

f.close()

 

f = open('json_file')

dic2 = json.load(f)  #load方法接收一个文件句柄,直接将文件中的json字符串转换成数据结构返回

f.close()

print(type(dic2),dic2)

7.2.3 ensure_ascii关键字参数

import json

f = open('file','w')

json.dump({'国籍':'中国'},f)

ret = json.dumps({'国籍':'中国'})

f.write(ret+'\n')

json.dump({'国籍':'美国'},f,ensure_ascii=False)

ret = json.dumps({'国籍':'美国'},ensure_ascii=False)

f.write(ret+'\n')

f.close()

7.3 pickle

7.3.1 json & pickle模块的区别

用于序列化的两个模块

 

json,用于字符串 和 python数据类型间进行转换

pickle,用于python特有的类型 和 python的数据类型间进行转换

7.3.2 pickle

pickle模块提供了四个功能:dumpsdump(序列化,存)、loads(反序列化,读)、load  (不仅可以序列化字典,列表...可以把python中任意的数据类型序列化)

 

import pickle

dic = {'k1':'v1','k2':'v2','k3':'v3'}

str_dic = pickle.dumps(dic)

print(str_dic)  #一串二进制内容

 

dic2 = pickle.loads(str_dic)

print(dic2)    #字典

 

import time

struct_time  = time.localtime(1000000000)

print(struct_time)

f = open('pickle_file','wb')

pickle.dump(struct_time,f)

f.close()

 

f = open('pickle_file','rb')

struct_time2 = pickle.load(f)

print(struct_time2.tm_year)

 

 

这时候机智的你又要说了,既然pickle如此强大,为什么还要学json呢?

这里我们要说明一下,json是一种所有的语言都可以识别的数据结构。

如果我们将一个字典或者序列化成了一个json存在文件里,那么java代码或者js代码也可以拿来用。

但是如果我们用pickle进行序列化,其他语言就不能读懂这是什么了~

所以,如果你序列化的内容是列表或者字典,我们非常推荐你使用json模块

但如果出于某种原因你不得不序列化其他的数据类型,而未来你还会用python对这个数据进行反序列化的话,那么就可以使用pickle

7.4 shelve

shelve也是python提供给我们的序列化工具,比pickle用起来更简单一些。

shelve只提供给我们一个open方法,是用key来访问的,使用起来和字典类似。

7.4.1 shelve

import shelve

f = shelve.open('shelve_file')

f['key'] = {'int':10, 'float':9.5, 'string':'Sample data'}  #直接对文件句柄操作,就可以存入数据

f.close()

 

import shelve

f1 = shelve.open('shelve_file')

existing = f1['key']  #取出数据的时候也只需要直接用key获取即可,但是如果key不存在会报错

f1.close()

print(existing)

这个模块有个限制,它不支持多个应用同一时间往同一个DB进行写操作。所以当我们知道我们的应用如果只进行读操作,我们可以让shelve通过只读方式打开DB

7.4.2 shelve只读

import shelve

f = shelve.open('shelve_file', flag='r')

existing = f['key']

f.close()

print(existing)

由于shelve在默认情况下是不会记录待持久化对象的任何修改的,所以我们在shelve.open()时候需要修改默认参数,否则对象的修改不会保存。

7.4.3 设置writeback

import shelve

f1 = shelve.open('shelve_file')

print(f1['key'])

f1['key']['new_value'] = 'this was not here before'

f1.close()

 

f2 = shelve.open('shelve_file', writeback=True)

print(f2['key'])

f2['key']['new_value'] = 'this was not here before'

f2.close()

 

writeback方式有优点也有缺点。优点是减少了我们出错的概率,并且让对象的持久化对用户更加的透明了;但这种方式并不是所有的情况下都需要,首先,使用writeback以后,shelfopen()的时候会增加额外的内存消耗,并且当DBclose()的时候会将缓存中的每一个对象都写入到DB,这也会带来额外的等待时间。因为shelve没有办法知道缓存中哪些对象修改了,哪些对象没有修改,因此所有的对象都会被写入。

8、正则表达式

在线测试工具 http://tool.chinaz.com/regex/

8.1 元字符

 

#[]字符集 []中的所有内容只匹配一个字符

#-范围[0-9] ascii码从小到大

#大小写遇到一起匹配所有字符,如\w\W能匹配所有字符

 

匹配小数:\d+\.\d+

匹配数字或小数:

\d+\.?\d*

\d+(\.?\d*)?

8.2 量词 * + ? {}

 

8.2.1 贪婪匹配

 

回溯算法:贪婪匹配的本质

先匹配第一个,然后一直匹配到最后再往前匹配直到匹配到

8.2.2 非贪婪匹配

前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配

*?  +?  ?? . {}?

 

几个常用的非贪婪匹配Pattern

*? 重复任意次,但尽可能少重复

+? 重复1次或更多次,但尽可能少重复

?? 重复0次或1次,但尽可能少重复

{n,m}? 重复nm次,但尽可能少重复

{n,}? 重复n次以上,但尽可能少重复

 

.*?的用法

. 是任意字符

* 是取 0 至 无限长度

? 是非贪婪模式。

何在一起就是 取尽量少的任意字符,一般不会这么单独写,他大多用在:

 

.*?x

就是取前面任意长度的字符,直到一个x出现

8.3 . ^ $

 

8.4 [] [^]

字符集

 

8.5 分组 ()与 或 |[^

身份证号码是一个长度为1518个字符的字符串,如果是15位则全部�数字组成,首位不能为0;如果是18位,则前17位全部是数字,末位可能是数字或x,下面我们尝试用正则来表示:

 

8.6 转义符 \

 

9re模块

9.1 findall()

9.1.1

直接返回匹配的列表

ret = re.findall('a', 'eva egon yuan')  # 返回所有满足匹配条件的结果,放在列表里
print(ret) #结果 : ['a', 'a']

9.1.2 findall的优先级查询

findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可

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']

9.2 search()

匹配找到的第一个结果,结果用.group()来取值

if re.search():

   print(re.search().group())

ret = re.search('a', 'eva egon yuan').group()
print(ret) #结果 : 'a'
# 函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以
# 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。

9.3 match()

从头开始匹配,匹配找到的第一个结果,结果用.group()来取值

ret = re.match('a', 'abc').group()  # 同search,不过尽在字符串开始处进行匹配
print(ret)
#结果 : 'a'

9.4 split()

9.4.1

分割

ret = re.split('[ab]', 'abcd')  # 先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割
print(ret)  # ['', '', 'cd']

9.4.2 split的优先级查询

ret=re.split("\d+","eva3egon4yuan")
print(ret) #结果 : ['eva', 'egon', 'yuan']

ret=re.split("(\d+)","eva3egon4yuan")
print(ret) #结果 : ['eva', '3', 'egon', '4', 'yuan']

#在匹配部分加上()之后所切出的结果是不同的,
#没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项,
#这个在某些需要保留匹配部分的使用过程是非常重要的。

9.5 sub()

替换

ret = re.sub('\d', 'H', 'eva3egon4yuan4', 1)#将数字替换成'H',参数1表示只替换1个
print(ret) #evaHegon4yuan4

9.6 subn()

替换 并返回替换几次

ret = re.subn('\d', 'H', 'eva3egon4yuan4')#将数字替换成'H',返回元组(替换的结果,替换了多少次)
print(ret)

9.7 compile()

用相同的正则表达式匹配多个值时,可以用re.compile()

re.compile(   ,re.S) #所有的.可以匹配任意,包括换行符

obj = re.compile('\d{3}')  #将正则表达式编译成为一个 正则表达式对象,规则要匹配的是3个数字
ret = obj.search('abc123eeee') #正则表达式对象调用search,参数为待匹配的字符串
print(ret.group())  #结果 : 123

9.8 finditer()

finditer返回一个存放匹配结果的迭代器

ret = re.finditer('\d', 'ds3sy4784a')   #finditer返回一个存放匹配结果的迭代器
print(ret)  # <callable_iterator object at 0x10195f940>
print(next(ret).group())  #查看第一个结果
print(next(ret).group())  #查看第二个结果
print([i.group() for i in ret])  #查看剩余的左右结果

9.9 匹配标签

分组命名

(?P<name>)  (?P=name)

ret = re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>")
#还可以在分组中利用?<name>的形式给分组起名字
#获取的匹配结果可以直接用group('名字')拿到对应的值
print(ret.group('tag_name'))  #结果 :h1
print(ret.group())  #结果 :<h1>hello</h1>

ret = re.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>")
#如果不给组起名字,也可以用\序号来找到对应的组,表示要找的内容和前面的组内容一致
#获取的匹配结果可以直接用group(序号)拿到对应的值
print(ret.group(1))
print(ret.group())  #结果 :<h1>hello</h1>

10hashlib

Pythonhashlib提供了常见的摘要算法,如MD5SHA1等等

10.1 md5()

10.1.1 给密码设置密文

import hashlib
md5_obj = hashlib.md5()
md5_obj.update(bytes('李李李李李杰杰杰杰杰',encoding='utf-8'))
print(md5_obj.hexdigest())

 

一长串字符串md5后的结果和分次将这个字符串md5的结果是一模一样的,所以可以将大字符串分次md5

 

#存储密文密码
f = open('userinfo','w')
md5 = hashlib.md5()
md5.update(b'3714')
md5_value = md5.hexdigest()
f.write('alex|%s\n'%md5_value)
f.close()
pwd = input('pwd : ')
f = open('userinfo')
alex_info = f.readline().strip()
user,passwd = alex_info.split('|')
md5 = hashlib.md5(b'salt')
md5.update(bytes(pwd,encoding='utf-8'))
print(md5.hexdigest())
if passwd == md5.hexdigest():
    print('登录成功')

10.1.2 检验文件的一致性

#文字文件:逐行读

#视频文件:按字节读

# #检验文件的一致性的
import os
filesize = os.path.getsize('文章')
f = open('文章','rb')
md5_obj = hashlib.md5()
while filesize > 0 :
    readsize = 10 if filesize>10 else filesize
    content = f.read(readsize)
    md5_obj.update(content)
    filesize -= readsize
print(md5_obj.hexdigest())

10.2 加盐

加盐就是在给md5()传参数,这样可以防止密文被破解,检验文章一致性不用加盐

import hashlib
md5_obj = hashlib.md5(b'alex')
md5_obj.update(bytes('李李李李李杰杰杰杰杰',encoding='utf-8'))
print(md5_obj.hexdigest())

10.3 sha1

 

11logger模块

11.1 灵活配置日志级别,日志格式,输出位置

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')

11.2 配置参数

logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:

 

filename:用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中。

filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。

format:指定handler使用的日志显示格式。

datefmt:指定日期时间格式。

level:设置rootlogger(后边会讲解具体概念)的日志级别

stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件(f=open(test.log,w)),默认为sys.stderr。若同时列出了filenamestream两个参数,则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用户输出的消息

11.3 logger对象配置

#logger对象
def log(filename):

    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)
    fh = logging.FileHandler(filename,encoding='utf-8')
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    fh.setFormatter(formatter)
    logger.addHandler(fh)

    sh = logging.StreamHandler()
    formatter2 = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    sh.setFormatter(formatter2)
    logger.addHandler(sh)
    return logger
logger = log('log')
logger.debug('debug hello')
logger.warning('你好')

 

 

转载于:https://www.cnblogs.com/xiaojinyu/p/7535683.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值