python之路常用模块

---恢复内容开始---

什么是 模块:模块就是一个.py文件,里面封装了一类作用的函数,使用的时候只需要导入模块,调用其中相应功能的功能函数就好了。这样可以极大的提高开发效率,同时也能很好的维护我们的代码!

模块的导入:

#  导入整个模块或者包
1. import moudle
#  导入模块或者包中的所有内容
2. from moudle import *
#  从模块或者包导入一部分内容
3. from moudle import part 
#  从模块或者包导入一部分内容并命名为m
4. from moudle import part as m

collections模块:


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

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

from collections import namedtuple#导入collections 模块
point = namedtuple("point",["x","y","z","d"])
p = point(1,2,"e","f")#生成可以用名字来访问元素内容的tuple,相当于给元祖里的每个元素起了个名字,取值的时候就可以用这个名字直接将元素取出来。
print(p.x)# 1
print(p.y)# 2
print(p.z)# e
print(p.d)# f

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

使用list存储数据时,按索引访问很快,但是插入和删除元素就很慢了,因为lists是线性存储,数据量大的时候,插入和删除的效率很低。deque是为了高效实现插入和删除操作的双向列表,适合用于队列和堆栈

from collections import deque
q =deque(["a","b","c"])
q.append("x")#从最后增加
q.appendleft("y")#从左边增加
print(q)#deque(['y', 'a', 'b', 'c', 'x'])
q.pop()#从末尾删除
q.popleft()#从左边删除
print(q)#deque(['a', 'b', 'c'])

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

counter的主要用途是用来统计某个值出现的次数,它是一个无序的容器,以字典的键值对形式存储,其中元素作为字典的key,其计数作为value。计数器可以统计任意的数据类型(包括0和负数)

from collections import Counter
c = Counter("abcabcabcabcabcabcabc")
print(c)#Counter({'a': 7, 'b': 7, 'c': 7})

4.OrderedDict: 有序字典,让字典key保持顺序.

from collections import OrderedDict
d = dict([("a",1),("b",2),("c",3)])
print(d)#{'a': 1, 'c': 3, 'b': 2}#字典的key是无序的
od = OrderedDict([('b', 2), ('a', 1), ('c', 3)])
print(od)#OderedDict的key是有序的,并且OrderedDict key的顺序会按照插入的顺序排列,不是key本身的顺序

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

使用dict时,如果引用的key不存在,就会抛出KeyError.如果不希望报错,返回默认值的时候就可以用defaultdict

from collections import defaultdict
dd = defaultdict(lambda:"N/A")
dd["key1"] = "abc"
print(dd["key1"])#key1存在,返回abc
print(dd["key2"])#key2不存在返回默认值N/A

时间模块:

python中提供了三种方式来表示时间:时间戳、时间元祖、格式化的时间字符串

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

格式化字符串(Format String):"2017-08-08"

时间元祖(struct_time):时间元祖一共有九个元素(年,月,日,时,分,秒,一年中的第几周,一年中的第几天等。)

my_dict = defaultdict(list)
#
# for value in  values:
#     if value>66:
#         my_dict['k1'].append(value)
#     else:
#         my_dict['k2'].append(value)
# print(my_dict)
# from collections import defaultdict
# dd = defaultdict(lambda:"N/A")
# dd["key1"] = "abc"
# print(dd["key1"])#key1存在,返回abc
# print(dd["key2"])#key2不存在返回默认值N/A
 

时间戳是计算机能够实现的,时间字符是人能看懂得得时间,元祖则是用来操作时间的

几种格式的 转换:

 

import time#导入时间模块
#时间戳--->结构化时间
print(time.gmtime(1502232438.0))#UTF,与英国伦敦时间相同
print(time.localtime(1502232438.0))#当地时间
#结构化时间--->时间戳
#time.mktime("结构化时间")
print(time.mktime(time.localtime()))#1502232438.0
#字符串时间---->结构化时间
# time.strptime(时间字符串,字符串对应的格式)
print(time.strptime("2017-08-09","%Y-%m-%d"))
print(time.strptime("2017/08/09","%Y/%m/%d"))
# 格式化时间----->字符串时间
# time.strftime("格式定义","结构化时间")结构化时间可以不传,默认当前时间
print(time.strftime("%Y-%m-%d"))#2017-08-09
print(time.strftime("%Y-%m-%d",time.localtime(300000000)))#1979-07-05

import time
#结构化时间---->格式化时间
#time.asctime(结构化时间)#不传参默认为当前时间
print(time.asctime(time.localtime(2000000000)))#Wed May 18 11:33:20 2033
print(time.asctime(time.localtime()))#Wed Aug  9 13:33:10 2017


# 格式化时间---->结构化时间
#time.ctime(时间戳)不传参,返回当前的格式化时间
print(time.ctime())#Wed Aug  9 13:37:00 2017
print(time.ctime(2000000000))#Wed May 18 11:33:20 2033

random模块

import random
#生成随机小数
print(random.random())
#0.9976510476137356生成0-1之间的小数
print(random.uniform(1,3))
# 2.8873739394057862生成小余3大余1的小数


# 随机整数
print(random.randint(1,5))#生成等于1且小于5之间的整数
print(random.randrange(1,10,2))#大于等于1且小于10之间的整数,指定步长为2


#随机返回一个值
random.choice([1,"23",[4,5]])
#随机返回多个值,返回的个数等于括号后面的参数
print(random.sample([1,"23",[4,5]],3))#[1, '23', [4, 5]]


#打乱顺序,洗牌
item= [1,2,3,4,5]
random.shuffle(item)#打乱顺序
print(item)
import random
def code():
    new_num = list(map(str,range(10)))
    alph = [chr(random.randint(65,91))]
    new_num.extend(alph)
    ret = [random.choice(new_num)for i in range(4)]
    return "".join(ret)
print(code())
print(code())
print(code())
生成随机验证码

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.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的大小
'''
os模块

sys模块

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

sys.argv           命令行参数List,第一个元素是程序本身路径
sys.exit(n)        退出程序,正常退出时exit(0)
sys.version        获取Python解释程序的版本信息
sys.maxint         最大的Int值
sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform       返回操作系统平台名称
sys模块

序列化模块

什么叫序列化模块,将原本字典、列表等内容换成一个字符串的过程叫做序列化。

每种编程语言都有各自的数据类型,其中面向对象的编程语言还允许开发者自定义数据类型,python也是一样,有时候我们会有这样的需求:

1,把内存中的各种数据类型通过网络传给其它的机器或者客户端;

2,把内存中的各种数据类型的数据保存在硬盘中持久化

这个时候就需要将各种数据序列化,序列化的反方向称为反序列化

json模块

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

import json
dic = {'k1':'v1','k2':'v2','k3':'v3'}
str_dic = json.dumps(dic)#序列化,将一个字典转成一个字符串
print(type(str_dic),str_dic)#<class 'str'> {"k1": "v1", "k2": "v2", "k3": "v3"}
#json转换完的字符串类型的字典中的字符串都是双引号

dic2 = json.loads(str_dic)#反序列化,将一个字符串格式的字典转换成一个字典
print(type(dic2),dic2)#<class 'dict'> {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
#用json 的loads功能处理的字符串类型的字典中的字符串必须是有双引号表示
dumps,loas
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)
dump,load

pickle

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

同python一样,dump和load 这两种方法都是关于文件的

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
strut_time = time.localtime(2000000000)
print(strut_time)
f = open('pickle_file','wb')#文件会产生乱码,不用管
pickle.dump(strut_time,f)
f.close()


f = open('pickle_file','rb')
strut_time2 = pickle.load(f)
print(strut_time)
pickle模块

shelve


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",'r')
existing = f1["key"]#取出数据的时候只需要直接用key获取即可,但是如果key不存在会报错
f1.close()
print(existing)
shelve

 hashlib

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

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

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

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

以MD5为例,,计算一个字符串的MD5值:

print('执行结果'.center(30,"*"))
import hashlib
md5 = hashlib.md5()
md5.update('how to use md5 in python hashlib?'.encode('utf-8'))
print(md5.hexdigest())
print('执行结果'.center(30,"*"))

# *************执行结果*************
# d26a53750bc40b38b65a520292f69306
# *************执行结果*************

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

print('执行结果'.center(30,"*"))
import hashlib

md5 = hashlib.md5() md5.update('how to use md5 in '.encode('utf-8'))
md5.update('python hashlib?'.encode('utf-8')) 

print(md5.hexdigest())

print('执行结果'.center(30,"*"))

# *************执行结果*************
#
d26a53750bc40b38b65a520292f69306
#
*************执行结果*************

MD5 是最常见得摘要算法,速度很快,生成结果是固定的128bit字节,通常用一个32位的16进制字符串表示,另一种常见的摘要算法是sha1,调用sha1和调用MD5完全一样:

print('执行结果'.center(30,"*"))
import hashlib
sha1 = hashlib.sha1()
sha1.update('how to use sha1 in python hashlib?'.encode('utf-8'))
print(sha1.hexdigest())
print('执行结果'.center(30,"*"))
# *************执行结果*************
# 2c76b57293ce30acef38d98f6046927161b46a44
# *************执行结果*************

SHA1的结果是160bit字节,通常用一个40位的16进制字符串表示。

撞库:

任何允许用户登录的网站都会存储用户的用户名和密码。这些数据都是被存放在数据库当中,如果以明文保存用户口令,一旦数据库泄露,所有的用户信息就会落入黑客手中,此外网站的运维人员是可以访问数据库的。也就是能获取到用户的信息。正确的保存用户信息的方式是摘要,如MD5。

但是由于每一组固定的数据的摘要也是固定的,所以黑客会提前做好一些反推表,如:

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

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

加盐:

由于一些常用的MD5值很容易被计算出来,为了确保用户信息不被泄露,要通过对原始口令加一个复杂的字符串来实现,俗称‘加盐’

hashlib.md5('salt'.encode('utf-8'))

经过salt处理的MD5口令,只要salt不泄露,即使用户输入简单口令,也很难被撞库。

如果假定用户无法修改用户名,那么就可以通过将登陆名作为salt的一部分来计算MD5值,从而实现相同口令的用户也存储不同的MD5:

import hashlib
user = 'lyon'#用户名改变,MD5值会跟着改变
pwd = '123'
md5 = hashlib.md5(user.encode('utf-8'))
md5.update(pwd.encode('utf-8'))
print(md5.hexdigest())

md5用于文件的校验:

import hashlib
f = open('filename')
md5_obj = hashlib.md5()
for line in f:#逐行校验
    md5_obj.update(line.encode('utf-8'))
md5_obj.hexdigest()
逐行校验
import hashlib
md5_obj = hashlib.md5()
import os 
filesize = os.path.getsize() #获取文件大小
f = open('filename','rb')
while filesize > 0:
    if filesize > 1024:#文件大于1024字节,执行以下代码
        content = f.read(1024)
        filesize -= 1024
    else:#否则,直接读取文件
        content = f.read(filesize)
        filesize -= filesize
    md5_obj.update(content)
md5_obj.hexdigest()
按字节校验

摘要算法在很对地方都得到广泛的应用,只要算法不是加密算法,因为摘要算法是一个不可逆的过程,只能用于防止篡改,但是它的单向设计特性也决定了可以在不存储明文口令的情况下验证用户口令。

 

configparser

该模块适用于配置文件的格式与windows ini文件类似,可以包含一个或者多个字节(section)

每个字节可以有多个参数(健 == 值)

创建一个配置文件:

import configparser
config = configparser.ConfigParser()#实例化一个对象
config['DEFAULT'] = {'ServerAliveInterval':45,
                       'Compression':'yes',
                       'CompressionLevel':'9',
                       'ForwardX11':'yes'
                      }
config['BitBucket.org'] =  {'User':'hg'}
config['TopSecret.server.com'] = {'Host Port':'50022','ForwardX11':'no'}
with open('example.ini','w') as f:
    config.write(f)#逐行写入文件
创建一个配置文件
[DEFAULT]
serveraliveinterval = 45
compression = yes
compressionlevel = 9
forwardx11 = yes

[BitBucket.org]
user = hg

[TopSecret.server.com]
host port = 50022
forwardx11 = no
创建出来的配置文件

查找文件:

import configparser
config = configparser.ConfigParser()
'----------------查找文件内容,基于字典形式---------------------'
config.read('example.ini')
# print(config.sections())#['BitBucket.org', 'TopSecret.server.com']
# print(config['DEFAULT']['Compression'])#yes
# print(config['BitBucket.org']['user'])#hg
# print(config['TopSecret.server.com']['ForwardX11'])#no

#支持for循环遍历

for key in config['TopSecret.server.com']:
    print(key)
#这里的[DEFAULT]只能取到自己的key
#['TopSecret.server.com']只能取到自己和[DEFAULT]的key
#[BitBucket.org]只能取到自己和[DEFAULT]的key
print(config.options('TopSecret.server.com'))#同for循环

print(type(config))#<class 'configparser.ConfigParser'>
print(config.items('TopSecret.server.com'))#取键值对
print(config.get('TopSecret.server.com','host port'))#取value

增删改操作:

import configparser
config = configparser.ConfigParser()
config.read('example.ini')
config.add_section('yuan')#增加一个section[yuan]  已经存在的section不能创建
config.remove_section('BitBucket.org')#删除一个section
config.remove_option('TopSecret.server.com','forwardx11')#删除一个section的item
config.add_section('Lyon')
config.set('Lyon','name','大腿')#为配置文件增加item
config.set('yuan','money','毛爷爷')
with open('example.ini', 'w') as configfile:#默认追写应该是
   config.write(configfile)
[DEFAULT]
serveraliveinterval = 45
compression = yes
compressionlevel = 9
forwardx11 = yes

[TopSecret.server.com]
host port = 50022

[yuan]
money = 毛爷爷

[Lyon]
name = 大腿
conf文件

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级别的日志,说明默认的日志级别为(critical>error>warning>info>debug),默认的日志格式为日志级别:logger名称:用户输出信息。

 

这里了解一下字符串的格式化输出另一种格式:

name = "alex"
age = 29
print('%(name)s,%(age)d '%{'name':'alex','age':29})

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

import logging
logging.basicConfig(level = logging.DEBUG,#配置日志级别
                    format = '%(asctime)s %(filename)s--%(message)s',#日志格式
                    datefmt = '%a/%d/%b/%Y %H:%M:%S',#日志格式
                    filename = 'logging_info',#输入位置,为logging_info 文件
                    filemode = 'w')#以写的模式
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')
Sat/19/Aug/2017 19:34:28 随笔.py--debug message
Sat/19/Aug/2017 19:34:28 随笔.py--info message
Sat/19/Aug/2017 19:34:28 随笔.py--warning message
Sat/19/Aug/2017 19:34:28 随笔.py--error message
Sat/19/Aug/2017 19:34:28 随笔.py--critical message
logging_info

配置参数:

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
def my_logger(filename,file =True,stream = True):
    logger = logging.getLogger()
    formatter  = logging.Formatter(fmt = '%(asctime)s %(filename)s [%(lineno)d]--%(message)s',
                                   datefmt= '%a/%d/%b %Y:%M:%S')
    formatter1  = logging.Formatter(fmt = '%(asctime)s %(filename)s [%(lineno)d]--%(message)s',
                                   datefmt= '%a-%d-%b %Y-%M-%S')
    # formatter 和 formatter1 可以调节输出到屏幕和文件的格式
    if file:
        logger.setLevel(logging.DEBUG)
        #输出到文件
        file_handler = logging.FileHandler(filename,encoding = ('utf-8'))
        file_handler.setFormatter(formatter)#关联formatter格式
        logger.addHandler(file_handler)
    if stream:
        #输出到屏幕
        stream_handler = logging.StreamHandler()
        stream_handler.setFormatter(formatter1)#关联formatter格式
        logger.addHandler(stream_handler)
    return logger
logger = my_logger('logging',stream=False)#可以在这里控制出入到屏幕还是文件
logging.debug('debug message')
logging.info('info message')

logging库提供了多个组件:Logger,Handler,Filter,Formatter.     Logger对象提供可直接使用的接口,Handler发送日志到适当的目的地,Filter 提供了过滤日志显示格式,另外,可以通过:Logger.self.evel(logging.Debug)设置级别。

 

 

 

 

 

 

 

 

 

 

 

 

posted on 2017-08-09 17:58  keepDoing  阅读(154)  评论(0编辑  收藏  举报

导航