首页 > 技术文章 > python基础7-常用模块

my-notebook 2018-01-29 16:16 原文

time模块(时间模块)
时间戳(timestamp):计算机认识的时间,通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。
格式化的时间字符串(Format String)
结构化的时间(struct_time):struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天,夏令时)
这三个时间的关系是:时间戳(time)与结构化(localtime)可以互为转换
结构化与格式化(strftime)可以互为转换
常用格式:%Y:年 %m:月 %d:日 %X:小时分钟秒 %w:周
import time
print(time.time()) #打印时间戳
print(time.strftime("%Y-%m-%d %X")) #格式化时间
print(time.localtime()) #本地时区的struct_time,根据时间戳打印时间,显示的结果是元组格式
print(time.gmtime()) #UTC时区的struct_time
print('今天是 %s 周%s' %(time.strftime('%Y-%m-%d'),time.strftime('%w')))
print(time.mktime(time.localtime())) #mktime(t) : 将一个struct_time转化为时间戳。
print(time.strftime('%Y-%m-%d %X',time.localtime(1473525749.0))) #根据时间戳格式化时间
print(time.asctime()) #显示的格式是“Sat Dec 16 14:09:34 2017”,什么也不填写,那么默认会向time.asctime()传递time.localtime()的结构化值
print(time.ctime(time.time())) #显示的格式与上述一致,什么也不填写,那么默认会向time.ctime()传递time.time()的时间戳
time.sleep(3) #线程推迟指定的时间运行,单位为秒。

random模块(用于生成随机数)
print(random.choice([1,2,'abcd',[3,4]])) #获取随机值,如果是列表就获取单个元素,如果是字符串,那么就是获取单个字符
print(random.sample([1,2,'a','b','c'],2)) #与上述相同,这个会获取两个随记值
print(random.uniform(1,3)) #生成一个指定范围内的随机符点数,两个参数其中一个是上限,一个是下限
a = [1,2,3,'a','v']
random.shuffle(a) #打乱列表中的顺序
print(a)

def suiji(n):
res = ''
for i in range(n):
s1 = chr(random.randint(65,90)) #chr表示ascii字符中的低65到90之际的值,这之间的值是英文的字母
s2 = str(random.randint(0,9)) #随记取值0到9之间数值
res += random.choice([s1,s2]) #每次随记取两个值,分别是数字和字母,每次二选一,最后生成9个随记码
return res
print(suiji(9))

print(random.randint(1, 3)) # [1,3] 大于等于1且小于等于3之间的整数
print(random.randrange(1, 3)) # [1,3) 大于等于1且小于3之间的整数


os模块(与操作系统交互的一个接口)
import os
res=os.system('netstat -ano |find "135"') #执行系统命令
print('==========================?>',res) #打印返回执行结果,0正确,非0这表示不正确
os.remove('conf') #删除文件,可以是相对路径
print(os.name) #显示当前的系统,windows是nt,linux是posix
os.rename('db.txt1','db.txt') #重命名
os.mkdir('abc') #创建目录
print(os.path.split(r'a\b\c\a.txt')) #返回值是('a\\b\\c', 'a.txt'),split分割路径和文件
print(os.path.dirname(r'a\b\c\a.txt')) #返回值是a\b\c,只显示路径
print(os.path.basename(r'a\b\c\a.txt')) #返回值是a.txt,只显示文件
print(os.path.abspath(r'a\b\c\a.txt')) #返回的路径是这个文件的绝对路径
print(os.path.exists(r'C:\pyfile\19-1\note\练习\db.txt')) #判断文件是存在,这个也可以判断目录是否存在
print(os.path.isdir(r'C:\pyfile\19-1\note\python\9')) #检查路径是否为目录,如果是则返回True,否则是False
print(os.stat(r'C:\pyfile\19-1\note\练习\hezi.jpg').st_size) #查看文件大小
print(os.path.getsize(r'C:\pyfile\19-1\note\练习\hezi.jpg')) #查看文件大小
print(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) #__file__表示当前文件的绝对路径,没执行一次dirname则返回上一级
print(os.path.normpath(os.path.join(os.path.abspath(__file__),'..','..'))) #先通过join对__file__拼接,然后在通过normpath规范路径
print(os.path.join('a','b','c')) #返回值是a\b\c,join是多个值拼接成路径

sys模块(sys模块操作 模块搜索路径、使用sys模块查找内建模块)
import time,random,os,sys
print(sys.argv[1]) #在执行python时可以在代码执行文件外向内传参数,以列表的形式展现,列表中第一位是代码文件,这里sys.argv[1]表示取列表中的值
print(sys.path) #python的环境变量
print(sys.exit(3)) #退出程序,正常退出时exit(0)

shutil模块(高级的 文件、文件夹、压缩包 处理模块)
shutil.copyfileobj(open('hezi.jpg','rb'),open('hezi1.jpg','wb')) #拷贝文件到另一个文件中
shutil.copyfile('hezi.jpg','hezi2.jpg') #拷贝文件,目标文件可以是不存在的
shutil.copymode('hezi.jpg','hezi2.jpg') #更改目标文件的权限为源文件的权限,内容,组用户均不变
shutil.copystat('base_web_new.css','linux_add_routes.sh') #更改目标文件的状态(修改日期),目标文件必须存在
shutil.copy('hezi.jpg','hezi3.jpg') #拷贝文件和权限
shutil.copy2('hezi.jpg','hezi4.jpg') #拷贝文件和状态
shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) #目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除
shutil.copytree('f1', 'f2', symlinks=True, ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) #通常的拷贝都把软连接拷贝成硬链接,即对待软连接来说,创建新的文件

shutil.rmtree('folder1') #递归的去删除文件
shutil.move('folder1', 'folder3') #递归的去移动文件,它类似mv命令,其实就是重命名
shutil.make_archive('bf.bak','gztar',root_dir=r'C:\pyfile\19-1\note\练习') #打包文件为tar.gz格式,名字是bf.bak

import tarfile
os.mkdir('bak')
jy = tarfile.open('rlx.bak.tar.gz') #解压缩包到bak文件夹中
jy.extractall('bak')
jy.close()

json&pickle模块(把对象(变量)从内存中变成可存储或传输的过程称之为序列化)
pickle:不能跨平台,但是对python支持较好
json:可以跨平台,但是对python的支持较少
注意:虽然pickle对python支持较多,但不是所以类型都需要pickle,比如函数,虽然json不能序列化,但是使用pickle序列化函数也只是序列了一个内存地址,这个内存地址不能独立存在,也就是说对于函数我们现用就可以,不需要序列化的,通常json的功能已经基本够用

import json
x={'name':'harry','age':25} #这是字典类型
print(type(x))
a=json.dumps(x) #json是字符串类型
print(type(a))

x={'name':'harry','age':25}
with open('1.json','w') as f:
f.write(json.dumps(x)) #保存json类型数据
with open('1.json','r') as f:
data = f.read()
print(json.loads(data)['name']) #反解json文件到python解释器
#注意,可以直接写一个json文件,然后用open读取文件反解出来,但是在json文件中不能使用单引号,只能使用双引号,比如{"a":11111111}这个是可以被json识别的
#loads传递的是json的字符串,也就是说不一定就非要使用dumps转换的格式,只要符合json格式的字符串都可以使用loads反解出来,比如:print(json.loads('{"name":"harry"}')['name'])也是可以的

x={'name':'harry','age':25}
json.dump(x,open('3.json','w')) #保存x的内容为json格式
print(json.load(open('3.json','r'))['name']) #读取json文件的内容
#注意:load和loads都能实现“反序列化”,但是loads是针对内存对象,load针对文件句柄

import pickle
d= {'a':1}
d_pik = pickle.dumps(d)
print(type(d_pik),d_pik) #结果是<class 'bytes'>,也就是说pickle是bytes类型
with open('1.pkl','wb') as f:
f.write(pickle.dumps(d)) #保存pickle格式
with open('1.pkl','rb') as f:
data = f.read()
print(pickle.loads(data)['a']) #反解pickle格式bytes

x={'a':1}
pickle.dump(x,open('2.pkl','wb'))
print(pickle.load(open('2.pkl','rb'))['a']) #方法与json的load和dump是一样的

shelve模块(shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写;key必须为字符串,而值可以是python所支持的数据类型)
import shelve
dic={'a':1,'b':2}
d=shelve.open(r'db.sh1') #序列化打开文件并传入值,在windows中会有三个文件,但是名字就是db.sh1
d['herry']={'pwd':'123','age':18}
d['x']=dic
d.close()

obj=shelve.open(r'db.sh1') #反解shelve
print(obj['herry'])
obj.close()

hashlib模块(hash:一种算法 ,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法)
三个特点:
1.内容相同则hash运算结果相同,内容稍微改变则hash值则变
2.不可逆推
3.相同算法:无论校验多长的数据,得到的哈希值长度固定。

import hashlib
m=hashlib.md5()
m.update('hello'.encode('utf-8'))
m.update('world'.encode('utf-8'))
print(m.hexdigest()) #fc5e038d38a57032085441e7fe7010b0

m=hashlib.md5()
m.update('helloworld'.encode('utf-8'))
print(m.hexdigest()) #fc5e038d38a57032085441e7fe7010b0
#结合上述两个比较,说明无论字符串是否为一行,只要内容是一致,那么哈希值就是一样的,所以如果要对比文件是否一致,而且文件过大,可以通过for循环一行行读取内容做比较

logging模块_1(日志模块)
日志级别:
critical=50
error=40
warning=30(默认级别是warning)
info=20
debug=10
notset=0
当设置日志级别为info级别,那么这个日志可以打印info日志以及warning、error、critical日志,也就是说打印的是设置级别及之后的日志,并且默认的输出目标是终端

import logging
logging.debug('debug')
logging.info('info')
logging.warning('warn')
logging.error('error')
logging.critical('critical')
#这个实例只能打印warning、error、critical日志,因为warning是默认级别

import logging
logging.basicConfig(
filename='access.log',
filemode='w',
format='%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
level=10
)
logging.debug('debug')
logging.info('info')
logging.warning('warn')
logging.error('error')
logging.critical('critical')
#logging.basicConfig这个日志是全局日志,所有的日志都会按照logging.basicConfig的设置显现

可在logging.basicConfig()函数中通过具体参数来更改logging模块默认行为,可用参数有
filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
format:指定handler使用的日志显示格式。
datefmt:指定日期时间格式。
level:设置rootlogger的日志级别
stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。

logging模块_2(日志模块)
#待解决的问题:
#1:既往终端打印,又往文件中打印
#2:控制输出到不同的目标(终端+文件)的日志,有各自的配置信息
解决上面两个问题,那么需要参考以下6步
第一步:通过logging.getLogger产生日志信息
第二步:filter过滤,不经常用,这里略
第三步:通过Handler接收日志然后控制FileHandler和StreamHandler打印到不同的地方
第四步:通过Formatter对象logging.Formatter定制不同的日志格式对象
第五步:为handler对象setFormatter(FileHandler和StreamHandler)绑定日志格式,并setLevel设置日志级别
第六步:把handler和formatter都add给logger,这样logger对象才能把自己的日志交给他们三负责输出

下面是完整的代码
import logging
logger = logging.getLogger('root') #logger=logging.getLogger('root')

h1 = logging.FileHandler('a.log') #h1=logging.FileHandler('t1.log')
h2 = logging.StreamHandler() #h3=logging.StreamHandler()

formatter1 = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
)
formatter2 = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
)

h1.setFormatter(formatter1) #h1.setFormatter(formatter1)
h2.setFormatter(formatter2) #h3.setFormatter(formatter2)
h1.setLevel(20)
h2.setLevel(20)

logger.addHandler(h1)
logger.addHandler(h2)
logger.setLevel(20)

logger.debug('debug')
logger.info('info')
logger.warning('warn123')
logger.error('error')
logger.critical('critical')

re模块(正则模块)

re.findall() :re.findall()函数将返回一个所有匹配的字符串的字符串列表。
print(re.findall('harry','123 hello harry 4%6&')) #匹配原理是在被匹配项中匹配harry的第一个字符也就是h这个字符,当匹配到h后在匹配a,依次类推直到完整的匹配harry,然后在y这个字符后面的字符开始继续匹配
print(re.findall('\w','123 hello harry 4%6&')) # 匹配数字和字符以及下划线
print(re.findall('\W','123 hello harry 4%6&')) #匹配空格和特殊字符
print(re.findall('\s','123 hello harry 4%6&')) #匹配空白
print(re.findall('\S','123 hello harry 4%6&')) #匹配非空白字符
print(re.findall('\d','123 hello harry 4%6&_')) #匹配数字
print(re.findall('\D','123 hello harry 4%6&_')) #匹配非数字
print(re.findall('\n','123\n hello harry 4%6&_')) #匹配换行
print(re.findall('\t','123\t hello harry 4%6&_')) #匹配tab
print(re.findall('\A1','123 hello harry 4%6&_')) #\A匹配字符串开头部分
print(re.findall('4%6&_\Z','123 hello harry 4%6&_')) #\Z匹配字符串结尾部分
print(re.findall('a.c','ac acc ac\n a\nc',re.S)) #在不加“re.S”的情况下,正则“.”无法匹配到“a\nc”,只能匹配到“acc”,这是因为字符串中\n表示的是换行符,也就是说a\nc a前面的字符串是一行,c后面的字符串是一行,在匹配是加re.S,表示“.”代表所有,也包括了\n
print(re.findall('ab?','a ac acb ab abb')) #匹配 ? 左面的字符0到1次,这是非贪婪匹配
print(re.findall('ab*','a ac acb ab abb')) #匹配 * 左面的字符0到多次
print(re.findall('ab+','a ac acb ab abb')) #匹配 + 左面的字符1到多次
print(re.findall('ab{1,}','a ac abbb ab abb')) #左面字符出现n到m次,在m位置不写范围,则表示匹配结束,这也是贪婪匹配,如果只写n,则是精确匹配
print(re.findall('a.*b','a123b456b')) #结果是['a123b456b'] ,这说明‘.*’是贪婪匹配的方式
print(re.findall('a.*?b','a123b456b')) #结果是['a123b'] ,这是‘.*?’非贪婪匹配,这是固定语法
print(re.findall('src="(.*JPG)"',
'<img class="s-news-img" src="http://www.littlibee.com/a.JPG" height="119" width="179">')) #当我们要匹配字符串时可以通过使用()分组的方式,只获取分组内的字符串,而其他字符串将不会被匹配到,而分组是正则的一个固定的符号,在使用时不需要加转义符号
print(re.findall('ab(?:c|d)','abc abd abe abf')) #结果是['abc', 'abd'] ,这里“?:”组合是一个固定语法,这表示当匹配到ab时第三位是c或者d都将匹配到

re.search() :与findall用户一致,不一样的地方在于search匹配一次就结束
print(re.search('harry','123 hello harry 4%6&_harry').group()) #

re.match() :match表示从头匹配
print(re.match('123','123 hello harry 4%6&_harry').group()) #在有.group()的情况下 如果开头部分匹配不到则报错,如果匹配到则返回结果,有没有.group()的情况下,匹配不到返回None

re.split() :分割字符串
print(re.split(':','nscd:x:28:28:NSCD Daemon:/:/sbin/nologin'))

re.subn() :
print(re.subn('harry','bob','123 hello harry 4%6&_harry')) #subn在替换时会统计替换了几次

re.sub() :替换
print(re.sub('harry','bob','123 hello harry 4%6&_harry',1)) #替换harry为bob,默认是替换全部,最后写1表示至替换一次
print(re.sub(r'(\w+)(\W+)(\w+)(\W+)(\w+)',r'\5\2\3\4\1','A and B')) #通过分组匹配字符,然后通过分组顺序排序

re.compile() :该函数根据包含的正则表达式的字符串创建模式对象
com=re.compile('\d') #用户complie创建一个正则模式对象
print(com.findall('123 hello harry 4%6&')) #结果是['1', '2', '3', '4', '6']

推荐阅读