我的python之旅呀-08持久化存储文件操作
一、文件操作
1、文件打开
使用 open() 函数
打开一个已经存在的文件,或者创建一个新文件
格式:open(文件名,访问模式)
默认的打开方式是’r’
f = open('doc/hello.txt', mode='w')
(1)如果文件不存在那么创建,如果存在那么就先清空,然后写入数据
(2)文件名最好写为绝对路径
(3)模式:
r | w | a | r+ | w+ | a+ |
---|---|---|---|---|---|
读 | 写 | 追加 | 读写 | 追加到文章开头 | 追加到文章末尾 |
(4)要读取二进制文件,比如图片、视频等等,用’rb’, ‘wb’, 'ab’等模式打开文件即可
2、文件对象的属性
属性 | 描述 |
---|---|
file.closed | 判断文件是否关闭,关闭返回True,否则返回False |
file.mode | 返回被打开文件的访问模式 |
file.name | 返回文件的名称 |
file.softspace | 如果用print输出后,必须跟一个空格符。则返回False,否则返回True |
3、文件对象的常用方法
1、读
file.read() #读取指定字节,默认1024
file.readline() #读取文件的一行内容
file.readlines() #读取文件的所有内容,返回一个列表,列表元素是每行内容
(1)文件比较小时,使用 read、readlines
(2)文件比较大时,使用readline
(3)其实在读的过程中,是有一个指针,从指针开始的地方开始读取。当读取完所有内容后,指针指到最后
文件对象时可迭代对象,可以通过for循环遍历每行
判断一个对象是否可迭代:导入模块,使用isinstance判断
from collection.abc import Iterable
f = open('etc/password','r')
print("文件对象是可迭代对象吗?",isinstance(f,Iterable)) # True
#循环遍历
for index, line in enumerate(f): #使用枚举列出每行
print("第%s行"%(index+1),line)
2、写
file.write() #从指针所在位置写入,写入字符串内容
file.writelines() #将列表里的每个元素写入文件
3、定位
file.tell() #指针当前所在位置
file.seek(offset,from) #移动指针位置
offset :偏移量
from: 方向
from只有三个值:
0 | 文件开头 |
---|---|
1 | 当前位置 |
2 | 文件末尾 |
file.seek(2,0) #先将指针移到文件开头,再向右移2
f = open('etc/password')
print(f.read())
f.write('hello')
f = open('doc/word.txt','a+') #追加方式打开,指针移动末尾
f.seek(0,0) #移动指针到最开始,才能读到内容
print(f.read())
f.write('hello python')
4、文件关闭
文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源, 并且操作系统同一时间能打开的文件数量也是有限的
方法一:
使用 file.close() 方法
方法二:
使用 with 语句(注意语句缩进)
with语句会自动调用close()方法
python中的with语句使用于对资源进行访问的场合,保证不管处理过程中是否发生错误或 者异常都会自动执行规定的(“清理”)操作,释放被访问的资源,比如有文件读写后自动 关闭、线程中锁的自动获取和释放等。
with open('/etc/password') as f: # as 起别名
print(f.closed) #False
print(f.readlines()[-1]) #读取最后一行
print(f.closed()) #True 此时已自动关闭文件
5、案例:
#将/etc/password文件后5行写入doc/world.txt文件
f1 = open('/etc/password','r')
f1_five = fi.readlines()[-5:]
f2 = open('doc/world.txt','w')
f2.writelines(f1_five)
print("write ok")
#忽略注释行
filename = 'doc/password.bak'
with open(filename) as f:
for line in f:
if not line.startswith('#'):
print(line)
#文件备份
import os
src_filename = input("要拷贝的文件:")
#判断文件是否存在
if os.path.exists(src_filename):
dst_filename = input("目标文件:")
#打开文件,读取文件
src_f = open(src_filename,'rb')
content = src_f.read()
#打开文件,写入文件
dst_f = open(dst_filename,'wb')
dst_f.write(content)
#关闭文件对象
src_f.close()
dst_f.close()
print("拷贝成功")
else:
print("要拷贝的文件不存在")
二、os模块
1、操作系统
os,语义为操作系统,处理操作系统相关的功能,可跨平台。 比如显示当前目录下所有文件/删除某个文件/获取文件大小……
使用前导入模块 os
(1)系统操作
import os
#返回操作系统类型:posix 是linux操作系统,nt 是windows
print(os.name)
#返回操作系统的详细信息
info = os.uname()
print(info.)
print(info.sysname)
print(info.nodename)
#返回系统环境变量
print(os.environ) #返回的是 字典 形式
#通过key值获取环境变量对应的value值
print(os.environ.get('PATH'))
print(os.getenv('PATH'))
(2)关于路径操作
import os
#判断是否为绝对路径
print(os.path.isabs(filename))
#生成绝对路径
print(os.path.abspath(filename))
#获取目录名和文件名
print(os.path.dirname(filename))
print(os.path.basename(filename))
#拼接路径
print(os.path.join('/mnt','hello','file.png')) # ‘/mnt/hello/file.png’
#返回当前所在文件的绝对路径
print(__file__)
#返回当前所在文件的目录名
print(os.path.dirname(__file__))
(3)关于文件与目录操作
#创建目录
os.makedirs('name')
os.mkdir('name')
#删除目录
os.rmdir('name')
#创建文件
os.mknod('name')
#删除文件
os.remove('name')
#文件重命名
os.rename('修改的文件名','新的文件名')
#判断文件或者目录是否存在
print(os.path.exists('name'))
#分割后缀名和文件名
print(os.path.splitext('hello.txt')) # ('hello','.txt')
print(os.path.split())
#分离目录名和文件名
print(os.path.split('/tmp/hello/hello.png'))
案例:
"""
项目需求: 批量验证码图片生成器
1). 可生成数字、大写、小写字母及三者混合类型的验证码
2). 支持自定义验证码字符数量
3). 支持自动调整验证码图片的大小
4). 支持自定义干扰点的数量
5). 支持自定义验证码图文颜色
"""
import random
import os
#随机生成验证码
def code(length = 4):
import string
strings = string.digits + string.ascii_letters
str_list = random.sample(strings,length) #生成的是数组形式,还要拼接成字符串
return "".join(str_list)
#绘制验证码图片 PIL模块
from PIL import Image, ImageDraw, ImageFont
#定义变量,用于画面的背景色,宽,高
while_color = (255,255,255)
black_color = (0,0,0)
rdm_color = (random.randint(0,255),random.randint(0,255),random.randint(0,255))
def draw_code_image(str_code, item_width=25, height=25, point_count=100,
bg_color=black_color, font_color=rdm_color):
#根据验证码长度自动调整画布的宽度
width = len(str_code) * item_width
#创建画布
im = Image.new('RGB',(width,height),bg_color)
#创建画笔
draw = ImageDraw.Draw(im) #将画笔与画布联系
#绘制噪点:调用画笔的point()函数
for i in range(point_count):
xy = (random.randrange(0,width),random.randrange(0,height)) #噪点坐标
draw.point(xy,fill=rdm_color)
#构造字体对象
font = ImageFont.truetype('C:\Users\Gaoqi\Desktop\新建文件夹\字体\思源宋体 SC-Bold.otf',25)
for index, item in enumerate(str_code):
draw.text((5 + (index * 25),0), item, font=font, fill=font_color)
return im
if __name__ == '__main__':
from tqdm import tqdm #显示进度
number = 10
dirname = 'vCode'
for count in tqdm(range(number)):
str_code = code()
#返回图片对象
im = draw_code_image(str_code)
#生成图片绝对路径
filename = os.path.join(dirname, str_code+random.choice(['.png','.jpg']))
im.save(filename)
三、json模块
1、定义:
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于ECMAScript的 一个子集。
JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C、 C++、Java、JavaScript、Perl、Python等)。
这些特性使JSON成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和 生成(一般用于提升网络传输速率)。
它可以与所有语言进行数据交换
使用需导入 import json
python–>json:编码(序列化)
json–>python :解码(反序列化)
python类型数据和JSON数据格式互相转换规则
pyhton中的集合不能转成json格式
2、实现编码解码
编码:
import json
info = dict(user1='0000', user2='1111')
#转成json数据格式
json_info = json.dumps(info)
print(info, json_info)
print(type(info),type(json_info))
运行结果:
#转成json并存储
json.dump(info, open('doc/info.json','w',indent=4, ensure_asscii=False))
解码:
import json
filename = 'doc/info.json'
#将文件中的json数据转换成python对象
python_info = json.load(open(filename))
print(python_info)
print(python_info.get('user1'))
常用参数:
json.dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, encoding=“utf-8”, default=None, sort_keys=False, ** kw)
• ensure_ascii=False: 中文存储需要设定
• indent=4: 增加缩进,增强可读性,但缩进空格会使数据变大
• separators=(’,’,’:’): 自定义分隔符,元素间分隔符为逗号, 字典key和value值的分隔符为冒号
• sort_keys=True: 字典排序
3、自定义数据类型编码解码
如果我们碰到集合对象, datetime对象,或者自定义的类对象等json默认不支持的数据类型时,我们就需要自定义编解码函数。
自定义编解码函数
import json
from datetime import datetime
from datetime import date
def time2str(dateObj)
return str(dateObj)
dt = datetime.now()
today = date.today()
with open('doc/date.json','w') as f:
#将today以time2str转换成字符串,再进行json编码,再保存到f文件中
json.dump(today,f,default=time2str)
四、pickle模块
1、定义
python的pickle模块实现了python的所有数据序列和反序列化。
与JSON不同的是pickle不是用于多种 语言间的数据传输,它仅作为python对象的持久化或者python程序间进行互相传输对象的方法,因此 它支持了python所有的数据类型。
cPickle是pickle模块的C语言编译版本相对速度更快。
2、json与pickle的区别
(1)json只能处理基本数据类型。pickle能处理所有Python的数据类型。
(2)json用于各种语言之间的字符转换。pickle用于Python程序对象的持久化或者Python程序间对象网络传输,但不同版本的Python序列化可能还有差异。
3、实现编码解码
from datatime import date
today = date.today()
#编码
with open('date.pkl','wb') as f:
pickle.dump(today,f)
#解码
with open('date.pkl','rb') as f:
today = pickle.load(f)
print(today)