前言:python中有众多的模块,下面我列举几个常用的模块。
第一:time模块
python中时间相关的操作,时间有三种表示方式:
时间戳 1970年1月1日之后的秒,运行“type(time.time())”,返回的是float类型。即:time.time()
格式化的字符串 2014-11-11 11:11,即:time.strftime('%Y-%m-%d')
结构化时间 struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天,夏令时) 即:time.localtime()
认识时间的形式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import time #首先认识三种形式的时间 print (time.time() 1492355202.6346803 #格式化的时间字符串: print (time.strftime( "%Y-%m-%d %X" )) #2017-04-16 23:06:42 #本地时区的struct_time print (time.localtime()) #time.struct_time(tm_year=2017, tm_mon=4, tm_mday=16, tm_hour=23, tm_min=6, tm_sec=42, tm_wday=6, tm_yday=106, tm_isdst=0) #UTC时区的struct_time print (time.gmtime()) #time.struct_time(tm_year=2017, tm_mon=4, tm_mday=16, tm_hour=15, tm_min=6, tm_sec=42, tm_wday=6, tm_yday=106, tm_isdst=0) |
时间之间的转换:
num1:
1
2
3
4
5
6
7
8
9
10
11
|
#时间戳转为结构化的时间 import time print (time.localtime()) print (time.gmtime()) print (time.localtime( 1483588666 )) print (time.gmtime( 1483588666 )) # time.struct_time(tm_year=2017, tm_mon=4, tm_mday=17, tm_hour=16, tm_min=53, tm_sec=27, tm_wday=0, tm_yday=107, tm_isdst=0) # time.struct_time(tm_year=2017, tm_mon=4, tm_mday=17, tm_hour=8, tm_min=53, tm_sec=27, tm_wday=0, tm_yday=107, tm_isdst=0) # time.struct_time(tm_year=2017, tm_mon=1, tm_mday=5, tm_hour=11, tm_min=57, tm_sec=46, tm_wday=3, tm_yday=5, tm_isdst=0) # time.struct_time(tm_year=2017, tm_mon=1, tm_mday=5, tm_hour=3, tm_min=57, tm_sec=46, tm_wday=3, tm_yday=5, tm_isdst=0) |
num2:
1
2
3
|
#结构化的时间转换为时间戳 print (time.mktime(time.localtime())) #1492419465.0 |
num3:
1
2
3
|
#结构化的时间转换为格式化的字符串时间 print (time.strftime( "%Y-%m-%d %X" , time.localtime())) #2017-04-17 17:06:23 |
num4:
1
2
3
|
#格式化的字符串时间转换为结构化的时间 print (time.strptime( '2017-04-17 17:05:06' , '%Y-%m-%d %X' )) #time.struct_time(tm_year=2017, tm_mon=4, tm_mday=17, tm_hour=17, tm_min=5, tm_sec=6, tm_wday=0, tm_yday=107, tm_isdst=-1) |
第二:os模块
os,语义为操作系统,所以肯定就是操作系统相关的功能了,可以处理文件和目录这些我们日常手动需要做的操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
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 输出用于分割文件路径的字符串 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所指向的文件或者目录的最后修改时间 |
os 路径处理:
os路径处理 #方式一: import os #具体应用,openstack源码中的使用方式 import os,sys possible_topdir = os.path.normpath(os.path.join( os.path.abspath(__file__), os.pardir, #上一级 os.pardir, os.pardir )) sys.path.insert(0,possible_topdir) #方式二:django中的使用方式 os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
第三: sys模块
sys:与python解释器进行交互
sys.argv 命令行参数List,第一个元素是程序本身路径,开发监控程序的时候会进程用到的 sys.exit(n) 退出程序,正常退出时exit(0) sys.version 获取Python解释程序的版本信息 sys.maxint 最大的Int值 sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 sys.platform 返回操作系统平台名称
第四: 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名称:用户输出消息。
#打印到文件 import sys import os project_path = os.path.dirname(os.path.abspath(__file__)) sys.path.append(project_path) 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='%s/log/log.txt'% project_path, filemode='w') logging.debug('debug message') logging.info('info message') logging.warning('warning message') logging.error('error message') logging.critical('critical message')
第五: random模块
import random print(random.random())#(0,1)----float 大于0且小于1之间的小数 print(random.randint(1,5)) #[1,5] 大于等于1且小于等于5之间的整数 print(random.randrange(1,5)) #[1,5) 大于等于1且小于5之间的整数 print(random.choice([1,'23',[4,5]]))#1或者23或者[4,5] print(random.sample([1,'23',[4,5]],2))#列表元素任意2个组合 print(random.uniform(1,3))#大于1小于3的小数,如1.927109612082716 item=[1,3,5,7,9] random.shuffle(item) #打乱item的顺序,相当于"洗牌" print(item)
第六:json&&pickle模块
首先要知道什么是序列化?
我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。
其次要明白为什么要有序列化?
1:持久保存状态
将状态保存在硬盘中
2:跨平台数据交互
序列化之后,不仅可以把序列化后的内容写入磁盘,还可以通过网络传输到别的机器上,如果收发的双方约定好实用一种序列化的格式,那么便打破了平台/语言差异化带来的限制,实现了跨平台数据交互
json介绍:
如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
Json模块提供了四个功能:dumps、dump、loads、load
常用的是dumps和loads,针对文件的操作
import json dic = {'name':'zzl','age':'18','sex':'male'} j=json.dumps(dic) f=open('test.txt','w') f.write(j) f.close() f=open('test.txt','r') data=json.loads(f.read()) print(data) {'sex': 'male', 'age': '18', 'name': 'zzl'}
pickle:
Pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据,不能成功地反序列化也没关系
pickle模块提供了四个功能:dumps、dump、loads、load
同样pickle常用的也是dumps和loads,针对文件的操作
import pickle dic = {'name':'zzl','age':'18','sex':'male'} j=pickle.dumps(dic) print(type(j)) #<class 'bytes'> f=open('pickle','wb')#由于j的类型是bytes,所以必须写入bytes,需要用wb的方式 f.write(j) f.close() #反序列化 f=open('pickle','rb') data=pickle.loads(f.read()) f.close() print(data) #{'age': '18', 'name': 'zzl', 'sex': 'male'}
第七:shutil模块
shutil模块是高级的 文件、文件夹、压缩包 处理模块。
import shutil #shutil.copyfileobj(fsrc, fdst[, length]) 拷贝文件内容 shutil.copyfileobj(open('test.txt','r'),open('test2.txt','w')) # shutil.copyfile(src, dst) 拷贝文件 shutil.copyfile('log.txt','log2.txt') # shutil.copymode(src, dst) 仅拷贝权限。内容、组、用户均不变 shutil.copymode('test.txt', 'log.txt') #目标文件必须存在 # shutil.copystat(src, dst) 仅拷贝状态的信息,包括:mode bits, atime, mtime, flags shutil.copystat('test.txt', 'test2.txt') #目标文件必须存在 # shutil.copy(src, dst) 拷贝文件和权限 shutil.copy('test.txt', 'test2.txt') #shutil.copy2(src, dst) 拷贝文件和状态信息 shutil.copy2('test.txt', 'test2.txt') # 递归的去拷贝文件夹 # shutil.ignore_patterns(*patterns) # shutil.copytree(src, dst, symlinks=False, ignore=None) shutil.copytree('log', 'folder', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) #目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除 shutil.copytree('log', 't2', symlinks=True, ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))#拷贝软连接文件,并且忽略已pyc和tmp结尾的 #shutil.rmtree(path[, ignore_errors[, onerror]])#递归的去删除文件 shutil.rmtree('folder2') # shutil.move(src, dst) 类似于mv命令,就是重命名 shutil.move('folder', 'folder3')
shutil.make_archive(base_name, format,...)
创建压缩包并返回文件路径,例如:zip、tar
创建压缩包并返回文件路径,例如:zip、tar
- base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
如 data_bak =>保存至当前路径
如:/tmp/data_bak =>保存至/tmp/ - format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
- root_dir: 要压缩的文件夹路径(默认当前目录)
- owner: 用户,默认当前用户
- group: 组,默认当前组
- logger: 用于记录日志,通常是logging.Logger对象
#将 /data 下的文件打包放置当前程序目录 import shutil ret = shutil.make_archive("data_bak", 'gztar', root_dir='/data') #将 /data下的文件打包放置 /tmp/目录 import shutil ret = shutil.make_archive("/tmp/data_bak", 'gztar', root_dir='/data')
shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,详细介绍:
import zipfile # 压缩 z = zipfile.ZipFile('laxi.zip', 'w') z.write('a.log') z.write('data.data') z.close() # 解压 z = zipfile.ZipFile('laxi.zip', 'r') z.extractall(path='.') z.close()
import tarfile # 压缩 >>> t=tarfile.open('/tmp/egon.tar','w') >>> t.add('/test1/a.py',arcname='a.bak') >>> t.add('/test1/b.py',arcname='b.bak') >>> t.close() # 解压 >>> t=tarfile.open('/tmp/egon.tar','r') >>> t.extractall('/egon') >>> t.close()
第八:shelve模块
shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写;key必须为字符串,而值可以是python所支持的数据类型。
先上一个错误示例(潜在的小问题)
import shelve f=shelve.open(r'sheve.txt') f['x']=['a','b','c'] f['x'].append('d') print(f['x']) f.close() #输出结果: ['a', 'b', 'c']
d 跑那里去了?其实很简单,d没有写回,你把['a', 'b', 'c']存到了x,当你再次读取s['x']的时候,s['x']只是一个拷贝,而你没有将拷贝写回,所以当你再次读取s['x']的时候,它又从源中读取了一个拷贝,所以,你新修改的内容并不会出现在拷贝中,解决的办法就是,第一个是利用一个缓存的变量,如下所示
import shelve f=shelve.open(r'sheve.txt') f['x']=['a','b','c'] tmp=f['x'] tmp.append('d') f['x']=tmp print(f['x']) f.close() #输出结果: ['a', 'b', 'c', 'd']
第九:configparser
软件的格式好多是以ini结尾的
[DEFAULT] ServerAliveInterval = 45 Compression = yes CompressionLevel = 9 ForwardX11 = yes [bitbucket.org] User = hg [topsecret.server.com] Port = 50022 ForwardX11 = no
1.获取所有的节点:(注意DEFAULT默认的是获取不到的)
import configparser config=configparser.ConfigParser() config.read('test.ini',encoding='utf-8') res=config.sections() print(res) 输出结果: ['bitbucket.org', 'topsecret.server.com']
2 获取指定节点下所有的键值对(会获取default的节点下的键值对和指定节点下的键值对,如果默认的键值对与指定节点下的键值对重复,则获取到的是指定节点下的键值对)
import configparser config=configparser.ConfigParser() config.read('test.ini',encoding='utf-8') res=config.items('topsecret.server.com') print(res) 输出结果: [('serveraliveinterval', '45'), ('compression', 'yes'), ('compressionlevel', '9'), ('forwardx11', 'no'), ('port', '50022')]
3.获取指定节点下的所有键
import configparser config=configparser.ConfigParser() config.read('test.ini',encoding='utf-8') res=config.options('bitbucket.org') print(res) 输出结果: ['user', 'serveraliveinterval', 'compression', 'compressionlevel', 'forwardx11']
4. 获取指定节点下指定key的值
import configparser config=configparser.ConfigParser() config.read('test.ini',encoding='utf-8') res1=config.get('bitbucket.org','user') res2=config.getint('topsecret.server.com','port') res3=config.getfloat('topsecret.server.com','port') res4=config.getboolean('topsecret.server.com','ForwardX11') print(res1) print(res2) print(res3) print(res4) 输出: hg 50022 50022.0 False
5.检测节点是否存在,添加节点,删除节点。
import configparser config=configparser.ConfigParser() config.read('test.ini',encoding='utf-8') #检查 has_sec=config.has_section('bitbucket.org') print(has_sec) #打印True,不存在则报错 #添加节点 config.add_section('zzl') #已经存在则报错 config['zzl']['username']='zhanling' config['zzl']['age']='18' config.write(open('test.ini','w')) # #删除节点 config.remove_section('zzl') config.write(open('test.ini','w'))
6.检查、删除、设置指定组内的键值对
import configparser config=configparser.ConfigParser() config.read('test.ini',encoding='utf-8') #检查 has_sec=config.has_option('bitbucket.org','user') #bitbucket.org下有一个键user print(has_sec) #打印True #删除 config.remove_option('DEFAULT','forwardx11') #删除DEFAULT节点下的forwardx11 config.write(open('test.ini','w')) #加载配置 #设置 config.set('zzl','username','zhangzhanling') #更改zzl节点下的username为zhangzhanling config.write(open('test.ini','w'))
7.新建一个ini的文件
import configparser config = configparser.ConfigParser() config["DEFAULT"] = {'ServerAliveInterval': '45', 'Compression': 'yes', 'CompressionLevel': '9'} config['bitbucket.org'] = {} config['bitbucket.org']['User'] = 'hg' config['topsecret.server.com'] = {} topsecret = config['topsecret.server.com'] topsecret['Host Port'] = '50022' # mutates the parser topsecret['ForwardX11'] = 'no' # same here config['DEFAULT']['ForwardX11'] = 'yes' with open('example.ini', 'w') as configfile: config.write(configfile)
第十:hashlib模块
hash:一种算法 ,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
三个特点:
1.内容相同则hash运算结果相同,内容稍微改变则hash值则变
2.不可逆推
3.相同算法:无论校验多长的数据,得到的哈希值长度固定。
import hashlib m=hashlib.md5()# m=hashlib.sha256() m.update('hello'.encode('utf8')) print(m.hexdigest()) #5d41402abc4b2a76b9719d911017c592 m.update('alvin'.encode('utf8')) print(m.hexdigest()) #92a7e713c30abbb0319fa07da2a5c4af m2=hashlib.md5() m2.update('helloalvin'.encode('utf8')) print(m2.hexdigest()) #92a7e713c30abbb0319fa07da2a5c4af ''' 注意:把一段很长的数据update多次,与一次update这段长数据,得到的结果一样 但是update多次为校验大文件提供了可能。 '''
以上的加密算法存在缺陷,可以通过撞库的方式破解,所以在加密算法中加入自定义的key
import hashlib # ######## 256 ######## hash = hashlib.sha256('898oaFsds09f'.encode('utf8')) hash.update('alvin'.encode('utf8')) print (hash.hexdigest())#e79e68f070cdedcfe63eaf1a2e92c83b4cfb1b5c6bc452d214c1b7e77cdfd1c7
python 还有一个 hmac 模块,它内部对我们创建 key 和 内容 进行进一步的处理然后再加密:
import hmac h = hmac.new('alvin'.encode('utf8')) h.update('hello'.encode('utf8')) print (h.hexdigest())#320df9832eab4c038b6c1d7ed73a5940
第十一:re正则
正则表达式(或 RE)是一种小型的、高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。
字符匹配(普通字符,元字符):
1 普通字符:大多数字符和字母都会和自身匹配
>>> re.findall('alvin','yuanaleSxalexwupeiqi')
['alvin']
2 元字符:. ^ $ * + ? { } [ ] | ( ) \
import re ret=re.findall('a..in','hellosahaelin') print(ret) # 解释:. 匹配一个字符 # 输出结果: # ['ahelin'] ret=re.findall('^a...n','aeeenadhfajkdh') print(ret) # 解释: ^ 匹配开头 # 输出结果: # ['aeeen'] ret=re.findall('a..v$','aasdfdassv') print(ret) # 解释: $ :匹配结危 # 输出结果: # ['assv'] ret=re.findall('abc*','abccc') print(ret) #贪婪匹配 # 输出结果: #['abcccc'] ret=re.findall('abc?','abcddcc') print(ret) # 解释:?:? 问号代表前面的字符最多只可以出现一次(0次、或1次) # 输出结果: #['abc'] ret=re.findall('abc{1,4}','abcccccc') print(ret) # 解释:{1,4}最多匹配4个 # 输出结果: #['abcccc'] 贪婪匹配
元字符之字符集[]:
#----------字符集[] 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 匹配一个特殊字符边界,比如空格 ,&,#等
ret=re.findall('I\b','I am LIST') print(ret)#[] ret=re.findall(r'I\b','I am LIST') print(ret)#['I']
元字符之分组()
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
元字符之|
ret=re.search('(ab)|\d','rabhdg8sd') print(ret.group())#ab
re模块下的常用方法
import re ret=re.findall('a','alvin yuan') print(ret) #解释:返回所有满足匹配条件的结果,放在列表里 # 输出结果: # ['a', 'a'] ret=re.search('a','alvin yuan').group() print(ret) #解释:函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以 # 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。 # 输出结果: # a ret=re.match('a','abc').group() print(ret) #解释: 同search,不过是在字符串开始处进行匹配 # 输出结果: # a ret=re.split('[ab]','abcd') print(ret) #解释:先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割 # 输出结果: #['', '', 'cd'] ret=re.sub('\d','abc','alvin5yuan6',1) print(ret) # 解释:把第一个数字替换成abc # 输出结果: #alvinabcyuan6 ret=re.subn('\d','abc','alvin5yuan6sss7') print(ret) # 解释:里面有几个字符就替换成几个abc # 输出结果: # ('alvinabcyuanabcsssabc', 3) obj=re.compile('\d{3}') ret=obj.search('abc123eeee') print(ret.group()) # 解释:匹配三个数字在一起的 # 输出结果: # abc
第十二:paramiko模块