目录
1. 文件和异常
实际开发中常常会遇到对数据进行持久化操作的场景,而实现数据持久化最好的办法就是将数据存储到文件中。如果想学习关于“文件”的知识,可以查看《鸟哥的Linux私房菜》一书。在python中实现文件的读写操作是利用内置的open函数,通过指定文件名,操作模式,以及对文件的编码格式来获取文件的对象。在此之前先来认识一下对文件的操作。
操作模式 | 具体含义 |
'r' | 读取(默认) |
'w' | 写入(会截断之前的内容) |
‘x’ | 写入(如果文件存在会产生异常) |
'a' | 追加(将内容写入到文件内容的末尾) |
'b' | 二进制模式 |
't' | 文本模式 |
'+' | 更新(可以读可以写) |
更多的详细内容请查看【菜鸟教程】
2. 读文件
读取文件时需要使用open函数指定要读取文件的路径和文件名,并将操作模式设置为 'r' ,当然默认值也是 'r',然后通过encoding参数指定编码(如果未指定,默认值为None,在读取文件的时候使用的是操作系统默认编码),要保证文件编码和encoding指定编码方式一致,不然会读取失败,经过实验得出编码格式只影响中文,对英语和数字并没有影响。
def main():
f = open('D:\Microsoft VS Code\pythonProject\Day1-15\ip.txt', 'r', encoding='GBK')
print(f.read())
f.close()
if __name__ == '__main__':
main()
在上面的代码里如果open在执行过程中遇到异常会产生致命错误,在正式的案例中读取文件肯定是很小的一部分代码块,为了保证代码的可用性,在python内使用异常机制来对运行的代码发生的异常进行处理。
# 分别改边文件名、encoding参数进行测试
def main():
f = None
try:
f = open('D:\Microsoft VS Code\pythonProject\Day1-15\ip.txt', 'r', encoding='ASCII')
print(f.read())
except FileNotFoundError:
print('文件不存在')
except LookupError:
print('指定了未知的编码!')
except UnicodeDecodeError:
print('读取文件时解码错误')
finally:
if f:
f.close()
if __name__ == '__main__':
main()
测试结果如下图:
在python中,由try所构成的代码块通尝是容易出现状况的代码,在try代码块后的except可以使用一个或者多个,利用它来捕获可能存在的异常情况。在上面的代码里如果文件不存在会引发FileNotFoundError ,指定了未知的编码会引发LookupError,如果读文件时编码方式错误会引发UnicodeDecodeError,在try后面的三个except分别处理这三种异常的情况。在最后使用代码块finally来关闭打开的文件,释放掉程序中的外部资源,在finally代码块的代码是不论程序正常还是异常都会执行,大佬的解释是(甚至是调用了sys
模块的exit
函数退出Python环境,finally
块都会被执行,因为exit
函数实质上是引发了SystemExit
异常),finally块称为“总是执行代码块”,适合用来释放外部资源。当然通过with关键字指定文件对象的上下文环境时自动释放资源。
def main():
f = None
try:
with open('D:\Microsoft VS Code\pythonProject\Day1-15\ip.txt', 'r', encoding='utf-8') as f:
print(f.read())
except FileNotFoundError:
print('文件不存在')
except LookupError:
print('指定了未知的编码!')
except UnicodeDecodeError:
print('读取文件时解码错误')
if __name__ == '__main__':
main()
当然除了使用文件对象read方法读取文件之外,还可以使用for-in循环逐行读取或者使用readline方法将文件按行读取到一个容器列表中,需要注意的是在使用readlines方法时会将文件包含的换行符、空格等一并读取。
import time
def main():
# 一次性读取整个文件内容
# with open('D:\Microsoft VS Code\pythonProject\Day1-15\ip.txt', 'r', encoding='utf-8') as f:
# print(f.read())
# 通过循环逐行遍历文件内容
with open('D:\Microsoft VS Code\pythonProject\Day1-15\ip.txt', mode='r', encoding='utf-8') as f:
for line in f:
print(line, end='')
time.sleep(0.5)
print()
# 按行读取文件内容
# with open('D:\Microsoft VS Code\pythonProject\Day1-15\ip.txt') as f:
# lines = f.readlines()
# print(lines)
if __name__ == '__main__':
main()
3. 写文件
明白了如何读取文件,写文件也就变得很简单了,在使用open函数时指定文件模式时更改为‘w’写入即可。如果对文件内容进行追加内容则要使用‘a’,此时如果文件不存在是不会发生异常得而是会新建一个文件将内容写入保存。
from math import sqrt
def is_prime(n):
"""判断为素数"""
assert n > 0
for factor in range(2, int(sqrt(n)) + 1):
if n % factor == 0:
return False
return True if n != 1 else False
def main():
filenames = ('a.txt', 'b.txt', 'c.txt')
fs_list = []
try:
for filename in filenames:
fs_list.append(open(filename, 'w', encoding='utf-8'))
# print(fs_list)
for number in range(1, 100):
if is_prime(number):
if number < 100:
fs_list[0].write(str(number) + '\n')
elif number < 1000:
fs_list[1].write(str(number) + '\n')
else:
fs_list[2].write(str(number) + '\n')
except IOError as ex:
print(ex)
print('写文件时发生意外!')
finally:
for fs in fs_list:
fs.close()
print('打完收工')
if __name__ == '__main__':
main()
4. 读写二进制文件
代码展示读取二进制文件
def main():
try:
with open('D:\Microsoft VS Code\pythonProject\Day1-15\image\\timg.jpg', 'rb') as f:
data = f.read()
print(type(data))
with open('D:\Microsoft VS Code\pythonProject\Day1-15\image\\小狗子.jpg', 'wb') as f1:
f1.write(data)
except FileExistsError as e:
print('文件不存在')
except IOError as e:
print('读写文件时出现错误')
print('执行结束')
if __name__ == '__main__':
main()
5. 读写JSON文件
学会了如何读取和保存文本内容,然而在现实的开发过程中并不会这么简单。当然随之而来的是要向文件中存什么数据和想文件中怎样存数据,如果需要将一个较大的多维数组保存到文件中应该如何做呢?别担心大佬已经帮助菜鸟本鸟解决了,那就是以JSON格式存储。JSON度娘的解释是"JavaScript Object Notation",需要注意的是它不是一个文件(本人一直以为它是一个文件),它是一个轻量级的数据交换格式,它完全独立于编程语言,被广泛的应用于跨平台语言的数据交换,因为它是纯文本格式,适用于任何编程语言。
{
"name": "jietewang",
"age": 11,
"call": 11111111111,
"skill": ["上刀山","下火海"],
"jobs": [
{"position": "xiaoluoluo", "Diachronic": 180},
{"position": "xiaoyuangong", "Diachronic": 280},
{"position": "daboss", "Diachronic": 380}
]
}
由上发现JSON跟字典类似,尝试把上面的内容保存为JSON。代码实例:
import json
def main():
mydict = {
"name": "jietewang",
"age": 11,
"call": 11111111111,
"skill": ["上刀山","下火海"],
"jobs": [
{"position": "xiaoluoluo", "Diachronic": 180},
{"position": "xiaoyuangong", "Diachronic": 280},
{"position": "daboss", "Diachronic": 380}
]
}
try:
with open('D:\Microsoft VS Code\pythonProject\Day1-15\image\\test.json', 'w', encoding='utf-8') as f:
json.dump(mydict, f)
except IOError as e:
print(e)
print('数据保存成功')
if __name__ == '__main__':
main()
json模块主要有四个比较重要的函数,分别是:
-
dump 将Python对象按照JSON格式序列化到文件中
-
dumps 将Python对象处理成JSON格式的字符串
-
load 将文件中的JSON数据反序列化成对象
-
loads 将字符串的内容反序列化成Python对象
新出现的概念就是序列化和反序列化,序列化的概念有点类似于系统镜像,将所有的东西一股脑的全封印了,要用的时候在解冻。具体的内容请自行百度。
接下来使用天行数据提供的新闻数据接口,使用requests模块请求网络api获取数据,通过json模块解析JSON数据并显示新闻的标题。
import json
import requests
def main():
resp = requests.get('http://api.tianapi.com/house/index?key=apiKey&num=10')
data_model = json.loads(resp.text)
for news in data_model['newslist']:
print(news['title'])
if __name__ == '__main__':
main()
代码执行结果: