collections模块

  在内置数据类型(dict、list、set、tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter、deque、defaultdict、namedtuple和OrderedDict等。

    1.namedtuple: 生成可以使用名字来访问元素内容的tuple

    2.deque: 双端队列,可以快速的从另外一侧追加和推出对象

    3.Counter: 计数器,主要用来计数

    4.OrderedDict: 有序字典

    5.defaultdict: 带有默认值的字典

  namedtuple (名称元祖)

  描述一类东西的时候,这类东西都有相同的特征,想直接用特征的名字就描述这个值的的时候就可以用命名元祖

  namedtuple是一个函数,它用来创建一个自定义的tuple对象,并且规定了tuple元素的个数,并可以用属性而不是索引来引用tuple的某个元素。

这样一来,我们用namedtuple可以很方便地定义一种数据类型,它具备tuple的不变性,又可以根据属性来引用,使用十分方便。

  namedtuple定义

  #namedtuple('名称', [属性list]):
  Circle = namedtuple('Circle', ['x', 'y', 'r'])
 from collections import namedtuple
point = namedtuple('Point', ['x', 'y'])
p = point(3, 4) print(p.x)
print(p.y)

deque (双端队列)

   使用list存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低。

   deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈

   deque除了实现list的append()pop()外,还支持appendleft()popleft(),这样就可以非常高效地往头部添加或删除元素

 from collections import deque

 dq = deque(['a', 'b', 'c'])
dq.append('x')
dq.appendleft('y') dq.pop()
dq.popleft()
print(dq)

deque

OrderedDict

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

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

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

 from collections import OrderedDict

 d = dict([('a', 2), ('c', 4), ('b', 6)])
# dict的key是无序的
print(d) od = OrderedDict([('a', 1), ('c', 3), ('b', 5)])
# OrderedDict的key是有序的
print(od) od['z'] = 6
od['y'] = 7
od['x'] = 8
print(od.keys()) # 按照插入的Key的顺序返回 {'a': 2, 'c': 4, 'b': 6}
OrderedDict([('a', 1), ('c', 3), ('b', 5)])
odict_keys(['a', 'c', 'b', 'z', 'y', 'x'])

OrderedDict

defaultdict

  使用dict时,如果引用的Key不存在,就会抛出KeyError。如果希望key不存在时,返回一个默认值,就可以用defaultdict

  注意默认值是调用函数返回的,而函数在创建defaultdict对象时传入。

    除了在Key不存在时返回默认值,defaultdict的其他行为跟dict是完全一样的

 from collections import defaultdict
values = [11, 22, 33, 44, 55, 66, 77, 88, 99]
my_dict = defaultdict(list) for value in values:
if value > 66:
my_dict['k1'].append(value)
elif value < 66:
my_dict['k2'].append(value) print(my_dict) defaultdict(<class 'list'>, {'k2': [11, 22, 33, 44, 55], 'k1': [77, 88, 99]})

defaultdict

Counter

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

 from collections import Counter
c = Counter('hello')
c1 = Counter({'a': 4, 'b': 2})
c2 = Counter(a=4, b=6)
print(c1)
print(c)
print(c2)

Counter

  当所访问的键不存在时,返回0,而不是KeyError;否则返回它的计数。

 from collections import Counter
c = Counter('abcdefgab')
print(c['a'])
print(c['h'])
print(c['d']) 2
0
1

计数值的访问

  可以使用一个iterable对象或者另一个Counter对象来更新键值。

  计数器的更新包括增加和减少两种。其中,增加使用update()方法和减少则使用subtract()方法

 from collections import Counter
c = Counter('which')
c.update('witch')
print(c['h']) d = Counter('watch')
c.update(d)
print(c['h']) c = Counter('which')
c.subtract('witch')
print(c['h']) d = Counter('watch')
c.subtract(d)
print(c['a']) 3
4
1
-1

键的修改和删除

当计数值为0时,并不意味着元素被删除,删除元素应当使用del

键的删除

>>> c = Counter("abcdcba")
>>> c
Counter({'a': 2, 'c': 2, 'b': 2, 'd': 1})
>>> c["b"] = 0
>>> c
Counter({'a': 2, 'c': 2, 'd': 1, 'b': 0})
>>> del c["a"]
>>> c
Counter({'c': 2, 'b': 2, 'd': 1})

elements()

返回一个迭代器。元素被重复了多少次,在该迭代器中就包含多少个该元素。元素排列无确定顺序,个数小于1的元素不被包含。

elements()方法 
>>> c = Counter(a=4, b=2, c=0, d=-2)
>>> list(c.elements())
['a', 'a', 'a', 'a', 'b', 'b']

most_common([n])

返回一个TopN列表。如果n没有被指定,则返回所有元素。当多个元素计数值相同时,排列是无确定顺序的。

most_common()方法

>>> c = Counter('abracadabra')
>>> c.most_common()
[('a', 5), ('r', 2), ('b', 2), ('c', 1), ('d', 1)]
>>> c.most_common(3)
[('a', 5), ('r', 2), ('b', 2)] 

浅拷贝copy

浅拷贝copy
>>> c = Counter("abcdcba")
>>> c
Counter({'a': 2, 'c': 2, 'b': 2, 'd': 1})
>>> d = c.copy()
>>> d
Counter({'a': 2, 'c': 2, 'b': 2, 'd': 1})

算术和集合操作

+、-、&、|操作也可以用于Counter。其中&和|操作分别返回两个Counter对象各元素的最小值和最大值。需要注意的是,得到的Counter对象将删除小于1的元素。

Counter对象的算术和集合操作
>>> c = Counter(a=3, b=1)
>>> d = Counter(a=1, b=2)
>>> c + d # c[x] + d[x]
Counter({'a': 4, 'b': 3})
>>> c - d # subtract(只保留正数计数的元素)
Counter({'a': 2})
>>> c & d # 交集: min(c[x], d[x])
Counter({'a': 1, 'b': 1})
>>> c | d # 并集: max(c[x], d[x])
Counter({'a': 3, 'b': 2})

其他常用操作

下面是一些Counter类的常用操作,来源于Python官方文档

Counter类常用操作

sum(c.values())  # 所有计数的总数
c.clear() # 重置Counter对象,注意不是删除
list(c) # 将c中的键转为列表
set(c) # 将c中的键转为set
dict(c) # 将c中的键值对转为字典
c.items() # 转为(elem, cnt)格式的列表
Counter(dict(list_of_pairs)) # 从(elem, cnt)格式的列表转换为Counter类对象
c.most_common()[:-n:-1] # 取出计数最少的n个元素
c += Counter() # 移除0和负值

                      时间模块

  表示时间的三种方式

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

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

    (2)格式化的时间字符串(Format String): ‘1999-12-06’

%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)元组(struct_time) :struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天等)

索引(Index) 属性(Attribute) 值(Values)
0 tm_year(年) 比如2011
1 tm_mon(月) 1 - 12
2 tm_mday(日) 1 - 31
3 tm_hour(时) 0 - 23
4 tm_min(分) 0 - 59
5 tm_sec(秒) 0 - 60
6 tm_wday(weekday) 0 - 6(0表示周一)
7 tm_yday(一年中的第几天) 1 - 366
8 tm_isdst(是否是夏令时) 默认为0
 import time
# time.sleep(10)
# 时间戳
print(time.time()) # 时间串
print(time.strftime('%Y-%m-%d %H:%M:%S'))
print(time.strftime('%A'))
print(time.strftime('%a'))
print(time.strftime('%x'))
print(time.strftime('%c')) # 时间元祖
print(time.localtime()) 1510645831.6729546
2017-11-14 15:50:31
Tuesday
Tue
11/14/17
Tue Nov 14 15:50:31 2017
time.struct_time(tm_year=2017, tm_mon=11, tm_mday=14, tm_hour=15, tm_min=50, tm_sec=31, tm_wday=1, tm_yday=318, tm_isdst=0)

几种格式之间的转换

 # 时间元祖
print(time.localtime(1500000000)) # 时间戳转换时间元祖
print(time.gmtime(1200000000)) # 英国时间
print(time.mktime(time.localtime(1500000000))) # 时间元祖转换时间戳 print(time.strftime('%Y-%m-%d', time.localtime(1500000000))) # 时间元祖转换时间串
print(time.strptime("2017-08-03", '%Y-%m-%d')) # 时间串转换时间元祖
print(time.strptime('2018/05/12', '%Y/%m/%d')) print(time.asctime(time.localtime(2000000000))) # 时间元祖转换时间串
print(time.ctime())
print(time.ctime(1600000000)) # 时间戳转换时间串

练习

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

计算时间差

sys模块

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

sys.argv           命令行参数List,第一个元素是程序本身路径
sys.exit(n) 退出程序,正常退出时exit(0),错误退出sys.exit(1)
sys.version 获取Python解释程序的版本信息
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform 返回操作系统平台名称
 import sys
print(sys.platform)
print(sys.version)
print(sys.path)
print(sys.argv)
print(sys.exit()) win32
3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)]
['C:\\Users\\panhw\\Desktop\\学习文档\\python\\day19作业', 'C:\\Users\\panhw\\Desktop\\学习文档\\python', 'C:\\Users\\panhw\\AppData\\Local\\Programs\\Python\\Python36\\python36.zip', 'C:\\Users\\panhw\\AppData\\Local\\Programs\\Python\\Python36\\DLLs', 'C:\\Users\\panhw\\AppData\\Local\\Programs\\Python\\Python36\\lib', 'C:\\Users\\panhw\\AppData\\Local\\Programs\\Python\\Python36', 'C:\\Users\\panhw\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages']
['C:/Users/panhw/Desktop/学习文档/python/day19作业/作业.py']

random模块

 import random

 # 随机小数
print(random.random()) # 随机生成0到1之间的小数
print(random.uniform(1, 10)) # 随机获取n到m之间的小数 # 0.11930423761507436
# 9.136906780912456 # 随机整数
print(random.randint(1, 5)) # 随机生成n到m之间的整数
print(random.randrange(10)) # 随机获取0到m之间的整数
print(random.randrange(2, 10)) # 随机生成n到m之间的整数
print(random.randrange(3, 15, 3)) # 随机生成n到m之间的整数 n的倍数 #
#
#
# # 随机选择序列的一个元素返回
print(random.choice(['a', 'b', 3, 4, 5, 8, 'v']))
# 随机返回选择序列的多个元素 返回的个数为取决于第二个参数
print(random.sample(['a', 'b', 3, 4, 5, 8, 'v'], 3)) # a
# ['a', 'b', 3] # 打乱原列表的顺序
item = [1, 2, 4, 5, 6, 7]
print(item)
random.shuffle(item)
print(item) # [1, 2, 4, 5, 6, 7]
# [1, 2, 4, 5, 6, 7]
 import random

 def verify(n=6):
"""
随机验证码
:param n: 验证码个数 (int)
:return: 返回验证码 (str)
"""
li = []
for i in range(n):
num = str(random.randint(0, 9)) # 随机整数转字符串
alpha = chr(random.randint(65, 90)) # 大写字母 ASCII
alpha2 = chr(random.randint(97, 122)) # 小写字母 ASCII
ret = random.choice([num, alpha, alpha2]) # 随机选择一个
li.append(ret)
return ''.join(li) # 列表转字符串 print(verify(8))

随机验证码

os模块

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

 import os
# 和系统路径相关
print(os.getcwd()) # 获取当前工作目录,即当前python脚本工作的目录路径os.chdir('C:\\Users') # 改变当前脚本工作目录;相当于shell下cd
print(os.getcwd())
print(os.curdir) # 返回当前目录: ('.')
print(os.pardir) # 获取当前目录的父目录字符串名:('..') # 和系统文件或文件夹相关的
os.mkdir('name1') # 生成单级目录;相当于shell中mkdir dirname
os.makedirs('name1/name2') # 可生成多层递归目录
os.rmdir('name1/name2') # 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.removedirs(r'C:\Users\panhw\Desktop\学习文档\python\day20\name1\name2') # 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
print(os.listdir(r'C:\Users\panhw\Desktop\学习文档\python\day20\name1')) # 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove(r'C:\Users\panhw\Desktop\学习文档\python\day4.py') # 删除一个文件
os.rename(r'name3/name4', 'name3/name') # 重命名文件/目录 # 和操作系统特征相关
print(os.stat(r'C:\Users\panhw\Desktop\学习文档\python\day4.py')) # 获取文件/目录信息
print(os.sep) # 输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
print(os.linesep) # 输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
print(os.pathsep) # 输出用于分割文件路径的字符串 win下为;,Linux下为:
print(os.name) # 输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
print(os.environ) # 获取系统环境变量 # 和操作系统命令相关
print(os.system('dir')) # 运行shell命令,直接显示
ret = os.popen('dir') # 运行shell命令,获取执行结果
print(ret.read()) # 和系统路径相关
print(os.path)
print(os.path.abspath('name3')) # 返回path规范化的绝对路径 os.path.split(path) 将path分割成目录和文件名二元组返回
print(os.path.dirname(r'C:\Users\panhw\Desktop\学习文档\python\day20\name3')) # 返回path的目录。其实就是os.path.split(path)的第一个元素
print(os.path.split(r'C:\Users\panhw\Desktop\学习文档\python\day20\name3')) # 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。
print(os.path.basename(r'C:\Users\panhw\Desktop\学习文档\python\day20\name3')) # 即os.path.split(path)的第二个元素
print(os.path.exists(r'C:\Users\panhw\Desktop\学习文档\python\day9.py')) # 如果path存在,返回True;如果path不存在,返回False
print(os.path.isabs(r'C:\Users\panhw\Desktop\学习文档\python\day9.py')) # 如果path是绝对路径,返回True
print(os.path.isfile(r'C:\Users\panhw\Desktop\学习文档\python\day9.py')) # 如果path是一个存在的文件,返回True。否则返回False
print(os.path.isdir(r'C:\Users\panhw\Desktop\学习文档\python\day9.py')) # 如果path是一个存在的目录,则返回True。否则返回False
print(os.path.join(r'C:\Users\panhw\Desktop', '学习文档', 'python', 'day9.py')) # 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
print(os.path.getsize(r'C:\Users\panhw\Desktop\学习文档\python\day9.py')) # 返回path的大小
print(os.path.getatime(r'C:\Users\panhw\Desktop\学习文档\python\day9.py')) # 返回path所指向的文件或者目录的最后访问时间
print(os.path.getmtime(r'C:\Users\panhw\Desktop\学习文档\python\day9.py')) # 返回path所指向的文件或者目录的最后修改时间

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

  stat 结构:

  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)是创建时间(详细信息参见平台的文档)。

序列化模块

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

  序列化的目的

    1、以某种存储形式使自定义对象持久化
    2、将对象从一个地方传递到另一个地方。
    3、使程序更具维护性。

json

  Json模块提供了四个功能:dumps、dump、loads、load

 import json
dic = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3', 'k4': 'v4'}
str_dic = json.dumps(dic) # 序列化:将一个字典转换成一个字符串
print(str_dic, type(str_dic))
# 注意,json转换完的字符串类型的字典中的字符串是由""表示的 dic2 = json.loads(str_dic) # 反序列化:将一个字符串格式的字典转换成一个字典
print(dic2, type(dic2))
#注意,要用json的loads功能处理的字符串类型的字典中的字符串必须由""表示 list_dic = [1, ['a', 'b', 'c'], 3, {'k1': 'v1', 'k2': 'v2'}]
str_dic = json.dumps(list_dic) # 也可以处理嵌套的数据类型
print(type(str_dic), str_dic) list_dic2 = json.loads(str_dic)
print(type(list_dic2), list_dic2)

dumps/loads

 import json
f = open('json_file', 'w', encoding='utf8')
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)

dump/load

 import json
f = open('file', 'w', encoding='utf8')
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()

pickle

用于序列化的两个模块

  • json,用于字符串 和 python数据类型间进行转换
  • pickle,用于python特有的类型 和 python的数据类型间进行转换

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

 import pickle
dic = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
str_dic = pickle.dumps(dic)
print(str_dic, type(str_dic)) # 一串二进制内容 dic2 = pickle.loads(str_dic)
print(dic2, type(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)
f.close()

pickle

如果我们将一个字典或者序列化成了一个json存在文件里,那么java代码或者js代码也可以拿来用。
但是如果我们用pickle进行序列化,其他语言就不能读懂这是什么了~
所以,如果你序列化的内容是列表或者字典,我们非常推荐你使用json模块
但如果出于某种原因你不得不序列化其他的数据类型,而未来你还会用python对这个数据进行反序列化的话,那么就可以使用pickle

shelve

  shelve也是python提供给我们的序列化工具,比pickle用起来更简单一些。
  shelve只提供给我们一个open方法,是用key来访问的,使用起来和字典类似。

 import shelve
f = shelve.open('shelve_file')
f['key'] = {'int': 10, 'float': 9.5, 'string': 'sample data'} # 直接对文件句柄操作,就可以存入数据
f.close() f1 = shelve.open('shelve_file') # 取出数据的时候也只需要直接用key获取即可,但是如果key不存在会报错
existing = f1['key']
f1.close()
print(existing)

shelve

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

 import shelve
f = shelve.open('shelve_file', flag='r')
existing = f['key']
f.close()
print(existing)

shelve只读

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

 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 after'
f2.close()

writeback=True

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

常用模块二 

hashlib模块

算法介绍

Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等。

什么是摘要算法呢?摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。

摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest,目的是为了发现原始数据是否被人篡改过。

摘要算法之所以能指出数据是否被篡改过,就是因为摘要函数是一个单向函数,计算f(data)很容易,但通过digest反推data却非常困难。而且,对原始数据做一个bit的修改,都会导致计算出的摘要完全不同。

我们以常见的摘要算法MD5为例,计算出一个字符串的MD5值:

 import hashlib

 md5 = hashlib.md5()
md5.update('how to use md5 in python hashlib?')
print md5.hexdigest() 计算结果如下:
d26a53750bc40b38b65a520292f69306

md5

如果数据量很大,可以分块多次调用update(),最后计算的结果是一样的:

 import hashlib

 sha1 = hashlib.sha1()
sha1.update('how to use sha1 in ')
sha1.update('python hashlib?')
print sha1.hexdigest()

分组MD5

SHA1的结果是160 bit字节,通常用一个40位的16进制字符串表示。比SHA1更安全的算法是SHA256和SHA512,不过越安全的算法越慢,而且摘要长度更长。

摘要算法应用

任何允许用户登录的网站都会存储用户登录的用户名和口令。如何存储用户名和口令呢?方法是存到数据库表中:

name    | password
--------+----------
michael | 123456
bob | abc999
alice | alice2008

如果以明文保存用户口令,如果数据库泄露,所有用户的口令就落入黑客的手里。此外,网站运维人员是可以访问数据库的,也就是能获取到所有用户的口令。正确的保存口令的方式是不存储用户的明文口令,而是存储用户口令的摘要,比如MD5:

username | password
---------+---------------------------------
michael | e10adc3949ba59abbe56e057f20f883e
bob | 878ef96e86145580c38c87f0410ad153
alice | 99b1c2188db85afee403b1536010c2c9

考虑这么个情况,很多用户喜欢用123456,888888,password这些简单的口令,于是,黑客可以事先计算出这些常用口令的MD5值,得到一个反推表:

'e10adc3949ba59abbe56e057f20f883e': '123456'
'21218cca77804d2ba1922c33e0151105': '888888'
'5f4dcc3b5aa765d61d8327deb882cf99': 'password'

这样,无需破解,只需要对比数据库的MD5,黑客就获得了使用常用口令的用户账号。

对于用户来讲,当然不要使用过于简单的口令。但是,我们能否在程序设计上对简单口令加强保护呢?

由于常用口令的MD5值很容易被计算出来,所以,要确保存储的用户口令不是那些已经被计算出来的常用口令的MD5,这一方法通过对原始口令加一个复杂字符串来实现,俗称“加盐”:

hashlib.md5("salt".encode("utf8"))

经过Salt处理的MD5口令,只要Salt不被黑客知道,即使用户输入简单口令,也很难通过MD5反推明文口令。

但是如果有两个用户都使用了相同的简单口令比如123456,在数据库中,将存储两条相同的MD5值,这说明这两个用户的口令是一样的。有没有办法让使用相同口令的用户存储不同的MD5呢?

如果假定用户无法修改登录名,就可以通过把登录名作为Salt的一部分来计算MD5,从而实现相同口令的用户也存储不同的MD5。

摘要算法在很多地方都有广泛的应用。要注意摘要算法不是加密算法,不能用于加密(因为无法通过摘要反推明文),只能用于防篡改,但是它的单向计算特性决定了可以在不存储明文口令的情况下验证用户口令。

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

简单的日志

配置参数:

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。若同时列出了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') # 再创建一个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对象配置

logging库提供了多个组件:Logger、Handler、Filter、Formatter。Logger对象提供应用程序可直接使用的接口,Handler发送日志到适当的目的地,Filter提供了过滤日志信息的方法,Formatter指定日志显示格式。另外,可以通过:logger.setLevel(logging.Debug)设置级别,当然,也可以通过

fh.setLevel(logging.Debug)单对文件流设置某个级别。

configparser模块

该模块适用于配置文件的格式与windows ini文件类似,可以包含一个或多个节(section),每个节可以有多个参数(键=值)。

创建文件

来看一个好多软件的常见文档格式如下:

[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes [bitbucket.org]
User = hg [topsecret.server.com]
Port = 50022
ForwardX11 = no

如果想用python生成一个这样的文档怎么做呢?

 import configparser

 config = configparser.ConfigParser()

 config["DEFAULT"] = {'ServerAliveInterval': '',
'Compression': 'yes',
'CompressionLevel': '',
'ForwardX11':'yes'
} config['bitbucket.org'] = {'User':'hg'} config['topsecret.server.com'] = {'Host Port':'','ForwardX11':'no'} with open('example.ini', 'w') as configfile: config.write(configfile)
 import configparser

 config = configparser.ConfigParser()

 #---------------------------查找文件内容,基于字典的形式

 print(config.sections())        #  []

 config.read('example.ini')

 print(config.sections())        #   ['bitbucket.org', 'topsecret.server.com']

 print('bytebong.com' in config) # False
print('bitbucket.org' in config) # True print(config['bitbucket.org']["user"]) # hg print(config['DEFAULT']['Compression']) #yes print(config['topsecret.server.com']['ForwardX11']) #no print(config['bitbucket.org']) #<Section: bitbucket.org> for key in config['bitbucket.org']: # 注意,有default会默认default的键
print(key) print(config.options('bitbucket.org')) # 同for循环,找到'bitbucket.org'下所有键 print(config.items('bitbucket.org')) #找到'bitbucket.org'下所有键值对 print(config.get('bitbucket.org','compression')) # yes get方法Section下的key对应的value

查找文件

 import configparser

 config = configparser.ConfigParser()

 config.read('example.ini')

 config.add_section('yuan')

 config.remove_section('bitbucket.org')
config.remove_option('topsecret.server.com',"forwardx11") config.set('topsecret.server.com','k1','')
config.set('yuan','k2','') config.write(open('new2.ini', "w"))

增删改操作

20 Python 常用模块的更多相关文章

  1. python常用模块-调用系统命令模块(subprocess)

    python常用模块-调用系统命令模块(subprocess) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. subproces基本上就是为了取代os.system和os.spaw ...

  2. python常用模块之shelve模块

    python常用模块之shelve模块 shelve模块是一个简单的k,v将内存中的数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据类型 我们在上面讲json.pickle ...

  3. python常用模块之shutil模块

    python常用模块之shutil模块 shutil模块,高级的文件.文件夹.压缩包处理模块 1.shutil.copyfile(src,des[,length]):将文件内容拷贝到另一个文件 In ...

  4. python常用模块之random模块

    python常用模块之random模块 在程序中很多会用到随机字符,比如登陆网站的随机验证码,通过random模块可以很容易生成随机字符串 1.random.randrange():返回1-10之间的 ...

  5. python 常用模块 time random os模块 sys模块 json & pickle shelve模块 xml模块 configparser hashlib subprocess logging re正则

    python 常用模块 time random os模块 sys模块 json & pickle shelve模块 xml模块 configparser hashlib  subprocess ...

  6. Python常用模块大全

    Python常用模块大全 os模块: os.remove() 删除文件 os.unlink() 删除文件 os.rename() 重命名文件 os.listdir() 列出指定目录下所有文件 os.c ...

  7. (转)python常用模块(模块和包的解释,time模块,sys模块,random模块,os模块,json和pickle序列化模块)

    阅读目录 1.1.1导入模块 1.1.2__name__ 1.1模块 什么是模块: 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代 ...

  8. Python常用模块之sys

    Python常用模块之sys sys模块提供了一系列有关Python运行环境的变量和函数. 常见用法 sys.argv 可以用sys.argv获取当前正在执行的命令行参数的参数列表(list). 变量 ...

  9. Python常用模块中常用内置函数的具体介绍

    Python作为计算机语言中常用的语言,它具有十分强大的功能,但是你知道Python常用模块I的内置模块中常用内置函数都包括哪些具体的函数吗?以下的文章就是对Python常用模块I的内置模块的常用内置 ...

随机推荐

  1. mapper文件提示:No data sources are configured to run this sql

    mapper文件发出黄色警告. 输入数据库用户名和密码等等. 自动同步ok 就会发现代码变绿了,ok

  2. win10笔记本触摸板手势大全

  3. css字体样式

    css字体样式(Font Style) 属性       css文本样式 序号 中文说明 标记语法 1 字体样式 {font:font-style font-variant font-weight f ...

  4. 常见Web源码泄露总结

    来自:http://www.hacksec.cn/Penetration-test/474.html 摘要 背景 本文主要是记录一下常见的源码泄漏问题,这些经常在web渗透测试以及CTF中出现. .h ...

  5. Funq之Lambda表达式入门

    今天接受了一个Tranning关于.net3.5 framework中的new feature. 其中最不明白的还是Lambda表达式.回来后又仔细的思考了一番,总算有点体会在这里写一下.既然是入门, ...

  6. cookie的路径和域

    1.Cookie的路径介绍 我们知道Cookie 的属性有很多,其中有一个属性是路径path.有些人认为Cookie 的路径指的是Cookie 在客户端的保存路径,其实并不是.Cookie 的路径是相 ...

  7. 建议40:深入掌握ConfigParser

    # -*- coding:utf-8 -*- ''' 1.getboolean() 根据一定的规则将配置项的值转换为布尔值 getboolean() 的真值规则: 0.no.false 和off 都会 ...

  8. P4755 Beautiful Pair

    题目 洛谷 做法 \(i≤x≤j,a[i]<\frac{a[x]}{a[j]}\) 考虑\(a[x]\)的贡献,单调栈预处理\(L,R\)能作为最大值的区间 枚举一端点,仅需另一端点满足条件即可 ...

  9. 自动生成Mapper代码

    public class BeanMapperTest { @Test public void build() throws Exception { Class clazz = RiskAccess. ...

  10. jenkins tomcat

    tomcat增加用户配置: <role rolename="tomcat"/> <role rolename="role1"/> < ...