「Python笔记13」素材存储:文件
一、操作文件
在Python中,操作文件包含3个步骤
- 调用 open() 函数打开物理文件,返回一个文件对象
- 调用文件对象的read() 或 write() 方法读写文件
- 调用文件对象关闭文件
1. 打开文件
Python 通过内置的open() 函数打开文件并创建该对象
open(file, mode='r', encoding=None)

参数mode是打开文件的模式
文件打开模式
| 模式 | 说明 |
|---|---|
| ‘r’ | 默认值,读模式,文件不存在触发FileNotFoundError异常 |
| ‘w’ | 写模式,文件不存在则创建,存在则覆盖 |
| ‘x’ | 写模式,文件不存在则创建,存在则触发FileExistError异常 |
| ‘a’ | 追加模式,文件不存在则创建,存在则在文件末尾追加内容 |
| ‘b’ | 以二进制方式打开文件 |
| ‘t’ | 默认值, 以文本文件方式打开文件 |
| ‘+’ | 结合 r/w/x/a 使用,创建可以同时读写的文件对象 |
参数encoding是指定文本文件读取数据时解码或写入数据时编码所用的规则,为默认值None时使用的规则取决于操作系统。
【例】查看当前系统的默认编码

2. 关闭文件
调用文件对象的close()方法可以关闭文件
file_obj.close()
3. 写入文本文件
当文件打开模式为 ‘w’、‘x’ 和 ‘a’ 时, 可以向文件中写入数据。使用文件对象的write()方法就可以将文本写入文件中
file_obj.write(text)
【例】用户输入商品名称和销售额,将输入的明细和合计信息存储到文件sales.txt中。
sales = []
sale_amt = 0
while True:
sale_info = input('请输入商品名称和销售额(用逗号隔开,直接回车结束):')
if len(sale_info) == 0:
break
goods_name, amount = sale_info.split(',')
sale_amt = sale_amt + float(amount)
sales.append([goods_name,amount])
sale_file = open('data/sales.txt', 'w', encoding='utf-8')
sale_file.write('销售明细: \n')
for goods_name, amount in sales:
sale_file.write(goods_name + ',' + amount + '\n')
sale_file.write('销售额合计: {:.2f} 元\n'.format(sale_amt))
sale_file.close()
执行结果:

运行结束后文件:

4. 读取文本文件
4.1 使用文件内置方法读取
| 方法 | 说明 |
|---|---|
| readall() | 以字符串形式返回整个文件内容 |
| readl(size = -1) | 默认读入从当前位置至文件末尾; 当size参数为大于0的正整数n时,从文件中最多读入n个字符 |
| readline(size = -1) | 默认从文件中读入一行内容; 当size参数为大于0的正整数n时,从文件中最多读入n个字符 |
| readlines(hint = -1) | 默认返回以文件中所有行为元素构成的列表; 当hint参数为大于0的正整数n时,读入的所有行字符数不超过n |
当打开文本文件时,会有一个指针指向文件开头的字符。每次读取数据后,指针会往后移动到相应位置。
文件内容全部读取后,指针指向文件尾部。如果需要从头读取文件内容,需要通过文件对象的seek() 方法将指针移动到文件开头,或者使用open() 函数重新打开文件
in_file = open('data/sales.txt', encoding='utf-8')
print(in_file.readline())
print(in_file.readline())
in_file.seek(0) # 将指针移动到文件开头
print(in_file.readline())
执行结果:

4.2 使用for循环逐行读取
在绝大多数情况下,对于文本文件的读取都是逐行读取。文件对象本身是一个可迭代对象。因此,通常情况下,推荐使用 for 循环来逐行读取文本文件内容。特别是在读取非常大的文本文件时,使用这种方式不会一次性将整个文件读入内存中,而是逐行读取,从而减轻内存压力。
in_file = open('data/sales.txt', encoding='utf-8')
for line in in_file:
print(line, end='')
in_file.close()

4.3 使用列表推导式和map()函数逐行读取
文件作为可迭代对象,可以使用列表推导式和map() 函数对每行进行相应处理,生成新的列表。
in_file = open('data/sales.txt', encoding='utf-8')
lines1 = [line.rstrip() for line in in_file]
print(lines1)
in_file.close()
lines2 = list(map(lambda line: line.rstrip(), open('data/sales.txt', encoding='utf-8')))
print(lines2)
执行结果:

5. 使用with语句自动管理
Python中的with语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会释放资源,比如文件使用后自动关闭
with open('data/sales.txt', encoding='utf-8') as sales_file:
for line in sales_file:
print(line, end = '')
执行结果:

二、使用pickle存储Python对象
如果将字典、列表数据, 存储到文件中,需要将对象构建成字符串,通过文件的write()方法写入文件。通过文件的read()方法读取的也是字符串,处理数据时,需要根据对应规则转换成列表或字典。这种好处时存储的文件可以直接通过其他文本编辑器打开查看。 但是缺点也很明显,需要对字符串进行来回转换。
在Python中,提供的pickle模块能够将Python对象直接存储到文件中。需要使用数据时,直接从文件中读取,并还原为Python对象。
注意,pickle操作的不是文本文件,而是二进制文件。
将Python对象存储到pickle文件的语法是:
pickle.dump(obj, file)
从pickle文件中将二进制数据读取出来重建为Python对象的语法是:
pickle.load(file)
import os
import pickle
stock_info = {'code':'600000','name':'浦发银行','price':11.54}
with open('data/stockinfo.pkl', 'wb') as stock_file:
pickle.dump(stock_info, stock_file) # 写文件
with open('data/stockinfo.pkl', 'rb') as stock_file:
ret_read = pickle.load(stock_file) # 读文件
print(type(ret_read))
print(ret_read)
执行结果:

三、使用JSON格式存储Python对象
JSON是一种和语言无关的轻量级数据交换格式,采用文本格式存储和表示数据。这种格式便于阅读和编写,也易于程序的解析和生成
JSON语法规则与Python中的字典和列表非常相似:
- 利用一对方括号[] 表示数组
- 利用一堆花括号{} 表示对象
- 利用冒号分隔键值对
- 利用逗号分隔数组的元素或对象的键值对
需要注意的是,在JSON格式的文本中,只能使用双引号表示字符值。
在Python中,可以通过标准库 json 方便地实现JSON格式字符串与Python字典和列表的相互转换
将Python对象转换为JSON格式字符串的语法是:
json.dumps(obj, ensure_ascii=True)
ensure_ascii默认值为True,如果对象中含有中文字符,应该设置为Flase,否则返回字符串中的中文为Unicode字节编码。该方法返回结果是转换后的字符串
将JSON格式字符串转换为Python对象的语法是:
json.loads(s)
其中,s是JSON格式字符串,该方法返回结果是对应的Python对象。
import json
stock_info = {'code':'600000','name':'浦发银行','price':11.54}
json_str = json.dumps(stock_info, ensure_ascii=False)
print(type(json_str))
print(json_str)
converted_dic = json.loads(json_str)
print(type(converted_dic))
print(converted_dic)
执行结果:

浙公网安备 33010602011771号