模块 (上)
一 time模块
在Python中,通常有这几种方式来表示时间:
时间戳(timestamp):通常来说,时间戳表示的是从1970年开始按秒计算的偏移量。
我们运行“type(time.time())”,返回的是float类型。
格式化的时间字符串(Format String)
结构化的时间(struct_time):struct_time元组共有9个元素共九个元素:
(年,月,日,时,分,秒,一年中第几周,一年中第几天,夏令时(is_dst))
import time
#我们先以当前时间为准,让大家快速认识三种形式的时间
print(time.time()) # 时间戳:1487130156.419527
# 1970年开始到现在的秒数,用于时间间隔的计算
# %X=%H:%M:%S %p(上午或者下午)
print(time.strftime("%Y-%m-%d %H:%M:%S %p"))
print(time.strftime("%Y-%m-%d %X %p"))
#格式化的时间字符串:'2017-02-15 11:40:53'
# 按照某种格式显示时间,用于展示时间
print(time.localtime()) #本地时区的struct_time
print(time.gmtime()) #UTC时区的struct_time
# 获取当前时间的某一部分
格式化字符串的时间格式其他用法———————————>>
二 datetime模块(时间加减)
import datetime
print(datetime.datetime.now()) #返回 2016-08-19 12:47:03.941925
print(datetime.date.fromtimestamp(time.time()) ) # 时间戳直接转成日期格式 2016-08-19
print(datetime.datetime.now() )
print(datetime.datetime.now() + datetime.timedelta(3)) #当前时间+3天
print(datetime.datetime.now() + datetime.timedelta(-3)) #当前时间-3天
print(datetime.datetime.now() + datetime.timedelta(hours=3)) #当前时间+3小时
print(datetime.datetime.now() + datetime.timedelta(minutes=30)) #当前时间+30分
c_time = datetime.datetime.now()
print(c_time.replace(minute=3,hour=2)) #时间替换
时间模块震要掌握的操作
# 1、时间格式的转换
#struct_time->时间戳
import time
s_time=time.localtime()
print(time.mktime(s_time))
时间戳->struct_time
tp_time=time.time()
print(time.localtime(tp_time))
structtime->格式化的字符串形式的时间
s_time=time.localtime()
print(time.strftime('%Y-%m-%d %H:%M:%S',s_time))
print(time.strptime('1988-03-03 11:11:11','%Y-%m-%d %H:%M:%S'))
**真正需要掌握的只有一条**:format string<------>timestamp
以1988-03-0311:11:11'+7举例
# format string-->struct_time--->timestamp
struct_time=time.strptime('1988-03-0311:11:11','%Y-%m-%d %H:%M:%S
timestamp=time.mktime(struct_time)+7*86400
print(timestamp)
# format string<--struct_time<---timestamp
res=time.strftime('%Y-%m-%d %X',time.localtime(timestamp))
print(res)
# 其他 time.sleep(3) # 比如让程序睡三秒
三 random模块
import random
print(random.random())#(0,1)----float 大于0且小于1之间的小数(只能(0,1)不能指定范围)
print(random.randint(1,3)) #[1,3] 大于等于1且小于等于3之间的整数
print(random.randrange(1,3)) #[1,3) 大于等于1且小于3之间的整数
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)
**应用:随机生成6位数验证码**
# ord('A')——>65, chr('65')———>'A'
# ord()函数主要用来返回对应字符的ascii码,
# chr()主要用来表示ascii码对应的字符他的输入时数字,
可以用十进制,也可以用十六进制。
import random
def make_code(size):
res=''
for i in range(size):
num=str(random.randint(0,9))
s= chr(random.randint(65,90))
res+=random.choice([num,s])
return res
res=make_code(6)
print(res)
四 os模块
**os模块:**与操作系统交互的一个接口(标*即重点,优先掌握)
* os.listdir('dirname') 获取指定文件夹下的子文件及子文件夹名字,包括隐藏文件,并以列表方式打印
* os.system("bash command") 运行shell命令,直接显示 ** 查看子文件夹查看子文件夹
* os.environ 获取系统环境变量
print(os.environ)
os.environ['aaa]='111' ,key跟value都得是字符串
PATH——>系统命令下,sys.path——>导模块
* os.path.getsize(path) 返回path的文件的大小(单位字节)
* os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素
print(os.path.dirname("E:/Read_File"))
结果:E:/
* os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
os.path.basename('c:\test.csv')
'test.csv'
* os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False
* os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False
* os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略,根据平台以/或\进行拼接
os.getcwd() 获取当前所在文件夹,即当前python脚本工作的目录路径
os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd
os.curdir 返回当前目录: ('.')
os.pardir 获取当前目录的上级目录字符串名:('..')
os.makedirs('dirname1/dirname2') 可生成多层递归目录,可以帮你生成子子文件夹
os.removedirs('dirname1') 若dirname文件下为空文件,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.remove() 删除一个文件
os.rename("oldname","newname") 重命名文件/目录
os.stat('path/filename') 获取文件/目录信息(针对linux系统)
os.sep 输出操作系统特定的路径分隔符,win下为"\\(第一个\对第二个\转义的意思)",Linux下为"/" (纯了解)
os.linesep 输出当前平台使用的行终止符,win下为"\r\n",Linux下为"\n"(纯了解)
os.pathsep 输出用于分割文件路径的字符串 win下为;,Linux下为:(纯了解)
os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.path.abspath(path) 返回path规范化的绝对路径 (windows系统'\' linux系统'/'符合平台需求)
import os
print(__file__)
print(os.path.abspath(__file__))
结果:c:/Users/PycharmProjects/bbb.py
C:\Users\PycharmProjects\bbb.py
os.path.split(path) 将path分割成目录和文件名二元组返回
os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path) 如果path是绝对路径,返回True
os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间
os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间
os.stat('path/filename') 获取文件/目录信息 的结构说明
五 sys模块
**基本用法**
1*sys.argv 命令行参数List,第一个元素是程序本身路径
2 sys.exit(n) 退出程序,正常退出时exit(0)
3 sys.version 获取Python解释程序的版本信息
4 sys.maxint 最大的Int值
5*sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
6 sys.platform 返回操作系统平台名称
* sys.argv
import sys
print(sys.argv)
src_file = input("请输入源文件路径>>>:").strip()
dst_file = input("请输入目标文件路径>>>:").strip()
src_file = sys.argv[1]
dst_file = sys.argv[2]
print(src_file)
print(dst_file)
with open(r'%s' %src_file,mode='rb') as f1,open(r'%s' %dst_file,mode='wb') as f2:
for line in f1:
f2.write(line)
* sys.path
**打印进度条**
#=========知识储备==========
#进度条的效果
[# ]
[## ]
[### ]
[#### ]
#指定宽度
print('[%-15s]' %'#')
print('[%-15s]' %'##')
print('[%-15s]' %'###')
print('[%-15s]' %'####')
#打印%
print('%s%%' %(100)) #第二个%号代表取消第一个%的特殊意义
#可传参来控制宽度
print('[%%-%ds]' %50) #[%-50s]
print(('[%%-%ds]' %50) %'#')
print(('[%%-%ds]' %50) %'##')
print(('[%%-%ds]' %50) %'###')
#=========实现打印进度条函数==========
import sys
import time
def progress(percent,width=50):
if percent >= 1:
percent=1
show_str=('[%%-%ds]' %width) %(int(width*percent)*'#')
print('\r%s %d%%' %(show_str,int(100*percent)),file=sys.stdout,flush=True,end='')
#=========应用==========
data_size=1025
recv_size=0
while recv_size < data_size:
time.sleep(0.1) #模拟数据的传输延迟
recv_size+=1024 #每次收1024
percent=recv_size/data_size #接收的比例
progress(percent,width=70) #进度条的宽度70
六shutil模块
shutil.copyfileobj(fsrc, fdst[, length])
将文件内容拷贝到另一个文件中
1 import shutil
2 shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))
shutil.copyfile(src, dst)
**拷贝文件**
1 shutil.copyfile('f1.log', 'f2.log') #目标文件无需存在
shutil.copymode(src, dst)
**仅拷贝权限**。内容、组、用户均不变
1 shutil.copymode('f1.log', 'f2.log') #目标文件必须存在
shutil.copystat(src, dst)
**仅拷贝状态的信息**,包括:mode bits, atime, mtime, flags
1 shutil.copystat('f1.log', 'f2.log') #目标文件必须存在
shutil.copy(src, dst)
**拷贝文件和权限**
1 import shutil
2
3 shutil.copy('f1.log', 'f2.log')
shutil.copy2(src, dst)
**拷贝文件和状态信息**
1 import shutil
2
3 shutil.copy2('f1.log', 'f2.log')
shutil.ignore_patterns(*patterns)
shutil.copytree(src, dst, symlinks=False, ignore=None)
**递归的去拷贝文件夹**
1 import shutil
2
3 shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) #目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除
import shutil
shutil.copytree('f1', 'f2', symlinks=True, ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))
'''
通常的拷贝都把软连接拷贝成硬链接,即对待软连接来说,创建新的文件
'''
shutil.rmtree(path[, ignore_errors[, onerror]])
**递归的去删除文件**
1 import shutil
2
3 shutil.rmtree('folder1')
shutil.move(src, dst)
**递归的去移动文件**,它类似mv命令,其实就是重命名。
1 import shutil
2
3 shutil.move('folder1', 'folder3')
shutil.make_archive(base_name, format,...)
**创建压缩包并返回文件路径**,例如:zip、tar
base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
如 data_bak =>保存至当前路径
如:/tmp/data_bak =>保存至/tmp/
format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
root_dir: 要压缩的文件夹路径(默认当前目录)
owner: 用户,默认当前用户
group: 组,默认当前组
logger: 用于记录日志,通常是logging.Logger对象
1 #将 /data 下的文件打包放置当前程序目录
2 import shutil
3 ret = shutil.make_archive("data_bak", 'gztar', root_dir='/data')
6 #将 /data下的文件打包放置 /tmp/目录
7 import shutil
8 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()
七 json模块&(pickle)
之前我们学习过用eval内置方法可以将一个字符串转成python对象,不过,eval方法是有局限性的,对于普通的数据类型,json.loads和eval都能用,但遇到特殊类型的时候,eval就不管用了,所以eval的重点还是通常用来执行一个字符串表达式,并返回表达式的值。
1 import json("")
2 x="[null,true,false,1]"
3 print(eval(x)) #报错,无法解析null类型,而json就可以
4 print(json.loads(x))
**什么是序列化?**
我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,
在Python中叫pickling,在其他语言中也被称为serialization,marshalling,flattening等等,都是一个意思。
**为什么要序列化?**
1:持久保存状态
需知一个软件/程序的执行就在处理一系列状态的变化,在编程语言中,
'状态'会以各种各样有结构的数据类型(也可简单的理解为变量)的形式被保存在内存中。
内存是无法永久保存数据的,当程序运行了一段时间,我们断电或者重启程序,
内存中关于这个程序的之前一段时间的数据(有结构)都被清空了。
在断电或重启程序之前将程序当前内存中所有的数据都保存下来(保存到文件中),
以便于下次程序执行能够从文件中载入之前的数据,然后继续执行,这就是序列化。
具体的来说,你玩使命召唤闯到了第13关,你保存游戏状态,关机走人,下次再玩,
还能从上次的位置开始继续闯关。或如,虚拟机状态的挂起等。
2:跨平台数据交互
序列化之后,不仅可以把序列化后的内容写入磁盘,还可以通过网络传输到别的机器上,
如果收发的双方约定好实用一种序列化的格式,那么便打破了平台/语言差异化带来的限制,
实现了跨平台数据交互。
反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
****json模块**是将满足条件的数据结构转化成特殊的字符串,并且也可以反序列化还原回去。**
上面介绍我已经说过了,序列化模块总共只有两种用法,要不就是用于网络传输的中间环节,
要不就是文件存储的中间环节,所以json模块总共就有两对四个方法:
**用于**网络传输**:dumps、loads**
**用于**文件写读**:dump、load**
dumps、loads
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) #反序列化:将一个字符串格式的字典转换成一个字典
#注意,要用json的loads功能处理的字符串类型的字典中的字符串必须由""表示
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'}]
创建text.json文件
import json
# 将**序列化**写入文件的复杂方法
json_res=json.dumps([1,'aaa',True,False])
print(json_res,type(json_res)) # [1, "aaa", true, false] <class 'str'>
with open('test.json',mode='wt',encoding='utf-8')as f:
f.write(json_res)
# 将序列化写入文件的简单方法(如果只是想把序列化内容写到文件里这样简单点)
with open('test.json',mode='wt',encoding='utf-8')as f:
json.dump([1,'aaa',True,False],f)
#**反序列化**
# 从文件读取json格式的字符串反序列化的结果写入文件的复杂方法
with open('text.json',mode='rt',encoding='utf-8')as f:
json_res=f.reas()
l=json.loads(json_res)
print(l,type(l)) #[1, 'aaa', True, False] <class 'list'>
# 从文件读取json格式的字符串反序列化的结果写入文件的简单方法
with open('text.json',mode='rt',encoding='utf-8')as f:
l=json.load(f) # 执行f.read操作-把文件内容读出来-然后调f.loads-把读出来的内容进行反解
print(l,type(l)) #[1, 'aaa', True, False] <class 'list'>
dump、load(针对文件相关)
import json
f = open('json_file.json','w')
dic = {'k1':'v1','k2':'v2','k3':'v3'}
json.dump(dic,f) #dump方法接收一个文件句柄,直接将字典转换成json字符串写入文件
f.close()
# json文件也是文件,就是专门存储json字符串的文件。
f = open('json_file.json')
dic2 = json.load(f) #load方法接收一个文件句柄,直接将文件中的json字符串转换成数据结构返回
f.close()
print(type(dic2),dic2)
八 pickle模块& (json)
pickle模块是将Python所有的数据结构以及对象等转化成bytes类型,然后还可以反序列化还原回去。
刚才也跟大家提到了pickle模块,pickle模块是只能Python语言识别的序列化模块。如果把序列化模块比喻成全世界公认的一种交流语言,也就是标准的话,json就是像是英语,全世界(python,java,php,C,等等)都遵循这个标准。而pickle就是中文,只有中国人(python)作为第一交流语言。
既然只是Python语言使用,那么它支持Python所有的数据类型包括后面我们要讲的实例化对象等,它能将这些所有的数据结构序列化成特殊的bytes,然后还可以反序列化还原。使用上与json几乎差不多,也是两对四个方法。
用于**网络传输**:dumps、loads
用于**文件写读**:dump、load
dumps、loads
import pickle
dic = {'k1':'v1','k2':'v2','k3':'v3'}
str_dic = pickle.dumps(dic)
print(str_dic) # bytes类型
dic2 = pickle.loads(str_dic)
print(dic2) #字典
# 还可以序列化对象
import pickle
def func():
print(666)
ret = pickle.dumps(func)
print(ret,type(ret)) # b'\x80\x03c__main__\nfunc\nq\x00.' <class 'bytes'>
f1 = pickle.loads(ret) # f1得到 func函数的内存地址
f1() # 执行func函数
dump、load
dic = {(1,2):'oldboy',1:True,'set':{1,2,3}}
f = open('pick序列化',mode='wb')
pickle.dump(dic,f)
f.close()
with open('pick序列化',mode='wb') as f1:
pickle.dump(dic,f1)
pickle序列化存储多个数据到一个文件中
dic1 = {'name':'oldboy1'}
dic2 = {'name':'oldboy2'}
dic3 = {'name':'oldboy3'}
f = open('pick多数据',mode='wb')
pickle.dump(dic1,f)
pickle.dump(dic2,f)
pickle.dump(dic3,f)
f.close()
f = open('pick多数据',mode='rb')
while True:
try:
print(pickle.load(f))
except EOFError:
break
f.close()
既然pickle如此强大,为什么还要学json呢?这里我们要说明一下,json是一种所有
的语言都可以识别的数据结构。如果我们将一个字典或者序列化成了一个json存在文件里,
那么java代码或者js代码也可以拿来用。但是如果我们用pickle进行序列化,其他语言就
不能读懂这是什么了~所以,如果你序列化的内容是列表或者字典,我们非常推荐你使用
json模块,但如果出于某种原因你不得不序列化其他的数据类型,而未来你还会用python
对这个数据进行反序列化的话,那么就可以使用pickle。
**其他**
# 序列化
# 内存中的数据类型------序列化-------》格式
# 内存中的数据类型《------反序列化-------格式
# **作用**:
# 1、**存档---》pickle**
# 2、**跨平台交互数据---》json**
# ==================>**json兼容所有语言,但是不支持所有的python数据类型**
(json验证:json格式兼容所有语言通用数据类型,不能识别某一语言所独有的类型)
# ==================> dumps--->loads
# import json
#
# str_json = json.dumps({"x":1,'y':2,'z':True,'a':None})
# print(str_json)
#
# dic = json.loads(str_json)
# print(dic)
# ====================> dump--->load
# import json
# json.dump({"x":1,'y':2,'z':True,'a':None},open('a.json',mode='wt',encoding='utf-8'))
# dic = json.load(open('a.json',mode='rt',encoding='utf-8'))
# print(dic)
# ===================> **pickle只适用于python,但是可以支持所有python的数据类型**
# ====================> dumps--->loads
# import pickle
#
# res_pkl = pickle.dumps({"x":1,'y':2,'z':True,'a':None})
# print(res_pkl)
#
# dic = pickle.loads(res_pkl)
# print(dic)
# ====================> dump--->load
# import pickle
#
# # pickle.dump({"x":1,'y':2,'z':True,'a':None},open('a.pkl',mode='wb'))
#
# dic = pickle.load(open('a.pkl',mode='rb'))
# print(dic)
import pickle
import json
# res = pickle.dumps({1,2,3,4,5,6})
res = json.dumps({1,2,3,4,5,6})
print(res)
jason-->t,用的多,跨平台 , pickle-->b,只适用于python