第十章 文件和异常
一、 读取文件
1、使用函数open()接受一个文件名的参数,在当前代码文件所在的目录查找指定的文件
2、文件的相对路径 让Python到指定的位置去查找,该位置相对于当前运行的程序所在目录的
3、文件的绝对路径 让Python到指定的绝对位置去查找
4、使用for循环进行逐行读取
5、创建一个包含文件各行内容的列表,就可在with代码块外访问列表
6、读取文件内容后使用文件的内容
7、读取一百万位长度的大型文件中的部分内容以及获取整个长度大小
8、查询文件内容中是否包含特定的值(以查询圆周率中是否包含生日为例)**
二、写入文件
1、将一行内容写入空文件
2、将多行内容写入文件
3、将内容附加写入文件末尾**
三、异常
1、处理ZeroDivisionError异常
2、使用异常避免崩溃
3、处理FileNotFoundError异常
4、计算txt文本包含多少单词使用split()方法
5、计算多个txt文本包含多少单词for循环文本列表
6、捕获到异常不提示时使用pass**
四、存储文件
1、使用将数据存储到json文件的json.dump()方法和从json文件加载数据的json.load()方法
2、保存和读取用户生成的数据
3、重构**
###################
10.1 读取文件
10.1.1 函数open()接受一个文件名的参数,在当前代码文件所在的目录查找指定的文件
with open('pi_digits.txt') as file_object:
#使用read方法读取这个文件的全部内容,并存储在变量中
contents = file_object.read()
#打印变量的值,使用rstrip()去空格
print(contents.rstrip())
#输出结果:
3.1415926535
8979323846
2643383279
#关键字with 在不再需要访问文件后将其关闭,也可以通过open()和close()来打开和关闭文件,如果程序有bug,导致close()语句未执行,文件将不会关闭
################
10.1.2 相对路径 让Python到指定的位置去查找,该位置相对于当前运行的程序所在目录的
#在代码文件目录新建一个test_file文件夹,然后放入文件(Windows中使用反斜杠)
with open('test_file\pi_digits.txt') as file_object:
contents = file_object.read()
print(contents)
#输出结果:
3.1415926
897932
2643
##################
10.1.3 绝对路径
#运行时提示路径不对。如果路径在Windows中可以访问,可以在开头添加r(如果后面的字符串有很多需要转义的符号时)
file_path = r'F:\PythonStudy\test_file\pi_digits.txt'
with open(file_path) as file_object:
contents = file_object.read()
print(contents)
#输出结果:
3.1415926
897932
2643
#################
10.1.4 逐行读取
#将文件名称存储在变量中
file_path = 'pi_digits.txt'
with open(file_path) as file_object:
#使用循环来遍历文件中的每一行
for file_line in file_object:
print(file_line)
#输出结果:
3.1415926535
8979323846
2643383279
#文件的换行符和print语句的换行符导致多余的空白行,可调用rstrip()去掉
################
10.1.5 创建一个包含文件各行内容的列表,就可在with代码块外访问列表
file_name = 'pi_digits.txt'
with open(file_name) as file_object:
#使用readlines()读取每一行并存储在列表中
lines = file_object.readlines()
for line in lines:
print(line.rstrip())
#输出结果:
3.1415926535
8979323846
2643383279
##################
10.1.6 使用文件的内容
file_name = 'pi_digits.txt'
with open(file_name) as file_object:
lines = file_object.readlines()
#创建一个变量用于存储圆周率的值
pi_string = ''
#使用for循环将各行都加入pi_string,并删除末尾换行符
for line in lines:
pi_string += line.rstrip()
#打印字符串和长度
print(pi_string)
print(len(pi_string))
#输出结果:精确到30位小数的圆周率值;长度为32位
3.141592653589793238462643383279
32
#读取文本文件时,Python将其中的所有文本解读为字符串;如果读取数字,并要将其作为数值使用,就必须使用int()将其转换为整数或使用函数float将其转换为浮点数
#################
10.1.7 包含一百万位的大型文件
filename = 'pi_digits.txt'
with open(filename) as file_object:
lines = file_object.readlines()
pi_string = ''
for line in lines:
pi_string += line.strip()
##获取文件内容前52位长度的值
print(pi_string[:52]+ "...")
##打印文件内容的总长度
print(len(pi_string))
#输出结果:前52位长度的值;文件内容总长度
3.14159265358979323846264338327924567892134564567498...
1090802
###################
10.1.8 查询圆周率中是否包含你的生日
#将生日表示为一个由数字组成的字符串,再检查这个字符串是否包含在文件的内容中
filename = 'pi_digits.txt'
with open(filename) as file_object:
lines = file_object.readlines()
pi_string = ''
for line in lines:
pi_string += line.strip()
#提示并获取用户输入的生日值,格式为:月日年
birthday = input("Enter your birthday,in the form mmddyy : ")
if birthday in pi_string:
print("Your birthday appears in the first million digits of pi!")
else:
print("Your birthday does not appear in the first million digits of pi.")
#输出结果:分别输入95年12月30日;95年13月30日
Enter your birthday,in the form mmddyy : 123095
Your birthday appears in the first million digits of pi!
Enter your birthday,in the form mmddyy : 133095
Your birthday does not appear in the first million digits of pi.
###################
10.2 写入文件
10.2.1 将一行内容写入空文件
filename = 'write_into.txt'
#调用open()时提供两个实参,一个文件名,一个以什么模式(下面有说明)打开文件
with open(filename,'w') as file_object:
#使用文件对象方法write()将一个字符串写入文件
file_object.write("This is for python write.")
#输出结果: 没有终端输出,打开write_into.txt文件查看内容
This is for python write.
#以上代码说明:
#第二个实参说明:读取模式(‘r’);写入模式(‘w’);附加模式(‘a’);读取和写入模式(‘r+’);省略此值的话默认只读
#写入文件不存在时,函数open()会自动创建;以写入模式打开文件时,如果文件已存在,python将在返回文件对象前清空该文件
#Python只能将字符串写入文本文件;要将数值存储到文本文件中,必须先使用函数str()将其转换为字符串格式
##################
10.2.2 将多行内容写入文件
filename = 'write_into.txt'
with open(filename,'w') as file_object:
file_object.write("This is for first A.\n")
file_object.write("This is for second B.\n")
file_object.write("This is for third C.")
#输出结果: 没有终端输出,打开write_into.txt文件查看内容;原来的内容被清空
This is for first A.
This is for second B.
This is for third C.
以上代码说明:
#如果没有换行符,写入文件后内容将显示在一行; 还可使用空格,制表符和空行来设置这些输出的格式
###################
10.2.3 将内容附加写入文件,添加到文件末尾
filename = 'write_into.txt'
#第二个实参说明:读取模式('r');写入模式('w');附加模式('a');读取和写入模式('r+');省略此值的话默认只读
with open(filename,'a') as file_object:
file_object.write("This is for forth D.")
#输出结果: 没有终端输出,打开write_into.txt文件查看内容;在原来的基础上附加
This is for first A.
This is for second B.
This is for third C.This is for forth D.
#####################
10.3 异常
#未对异常处理,程序将停止,并显示一个traceback,包含有关异常的报告;异常使用try-except代码块处理
10.3.1 处理ZeroDivisionError异常
#首先看看异常场景
print(5/0)
#输出结果
Traceback (most recent call last):
File "F:/PythonStudy/file_except.py", line 218, in <module>
print(5/0)
ZeroDivisionError: division by zero
#其次使用try-except代码块处理这个异常,程序可接着运行后面的代码
try:
print(5/0)
except ZeroDivisionError:
print("You can't divide by zero!")
#输出结果
You can't divide by zero!
#####################
10.3.2 使用异常避免崩溃
#如下代码是获取用户输入的两个数字进行除法运算; 但是为0时,就会抛出ZeroDivisionError异常,可以看到文件名称和部分代码,不利于安全
print("Give me two numbers,and I'll divide them.")
print("Enter 'q' to quit.")
while True:
#提示用户输入第一个数字,如果是q则退出
first_number = input("\nFirst number: ")
if first_number == 'q':
break
#提示用户输入第二个数字,如果是q则退出
second_number = input("Second number: ")
if second_number == 'q':
break
#计算两个数字的商
answer = int(first_number) / int(second_number)
print(answer)
######对以上代码进行异常处理改造后:
print("Give me two numbers,and I'll divide them.")
print("Enter 'q' to quit.")
while True:
#提示用户输入第一个数字,如果是q则退出
first_number = input("\nFirst number: ")
if first_number == 'q':
break
#提示用户输入第二个数字,如果是q则退出
second_number = input("Second number: ")
if second_number == 'q':
break
#使用try-except-else对异常进行处理
try:
answer = int(first_number) / int(second_number)
except ZeroDivisionError:
print("You can't divide by zero!")
else:
print(answer)
#输出结果:
First number: 5
Second number: 2
2.5
First number: 5
Second number: 0
You can't divide by zero!
#只有可能引发异常的代码才需要放在try语句中
#####################
10.3.3 处理FileNotFoundError异常
#先举例说明然后进行处理
filename = 'abcd.txt'
with open(filename) as file_object:
contents = file_object.read()
#输出结果:文件不存在时,出现FileNotFoundError异常
Traceback (most recent call last):
File "F:/PythonStudy/test_rumen/file_except.py", line 296, in <module>
with open(filename) as file_object:
FileNotFoundError: [Errno 2] No such file or directory: 'abcd.txt'
#出现以上问题后,通过try-except解决异常;open()函数打开文件异常,所以在open()之前添加try
filename = 'abcd.txt'
try:
with open(filename) as file_object:
contents = file_object.read()
except FileNotFoundError:
msg = "Sorry,the file " + filename + " does not exist."
print(msg)
#输出结果:
Sorry,the file abcd.txt does not exist.
#####################
10.3.4 分析文本
计算包含多少个单词使用split()方法
title = "Alice in Wonderland"
#方法split()以空格为分隔符将字符创拆成多个部分并存储到列表中
print(title.split())
#输出结果:列表
['Alice', 'in', 'Wonderland']
#计算文本包含多少个单词
filename = 'alice.txt'
try:
with open(filename) as f_obj:
contents = f_obj.read()
except FileNotFoundError:
msg = "Sorry, the file " + filename + " does not exist."
print(msg)
else:
# 计算文本包含多少单词
words = contents.split()
num_words = len(words)
print("The file " + filename + " has about " + str(num_words) + " words." )
#输出结果:
The file alice.txt has about 212 words.
#####################
10.3.5 使用多个文本
#将读取文本单词数的代码放到一个函数中
def count_words(filename):
"""计算一个文件大致包含多少单词"""
try:
with open(filename) as f_obj:
contents = f_obj.read()
except FileNotFoundError:
msg = "Sorry, The file " + filename + " does not exist."
print(msg)
else:
words = contents.split()
num_words = len(words)
print("The file " + filename + " has about " + str(num_words) + " words.")
#循环读取列表中的多个文本,即使文本不存在时也能正常执行后面的
filenames = ['alice.txt','notexist.txt','alice2.txt']
for filename in filenames:
count_words(filename)
#输出结果:
The file alice.txt has about 212 words.
Sorry, The file notexist.txt does not exist.
The file alice2.txt has about 212 words.
#####################
10.3.6 捕获到异常不提示时使用pass
def count_words(filename):
"""计算一个文件大致包含多少单词"""
try:
with open(filename) as f_obj:
contents = f_obj.read()
except FileNotFoundError:
#pass语句让python什么都不要做
pass
else:
words = contents.split()
num_words = len(words)
print("The file " + filename + " has about " + str(num_words) + " words.")
#循环读取列表中的多个文本,即使文本不存在时也能正常执行后面的
filenames = ['alice.txt','notexist.txt','alice2.txt']
for filename in filenames:
count_words(filename)
#输出结果:
The file alice.txt has about 212 words.
The file alice2.txt has about 212 words.
#####################
10.4 存储数据:使用模块json来存储数据;
模块json(JavaScript Object Notation)能够让简单的python数据结构转储到文件中,并在程序再次运行时加载该文件中的数据。分享数据。
10.4.1 使用json.dump()和json.load()
#使用json.dump()来存储数字列表,json.dump()接受两个实参,要存储的数据以及可用于存储数据的文件对象
#导入json模块
import json
#创建一个数字列表,也就是要存储的数据
numbers = [2,3,5,6,8,10,15,26]
#创建存储数据的文件,并以写入模式('w')打开
filename = 'numbers.json'
with open(filename,'w') as f_obj:
#json.dump()接受要存储的数据以及可用于存储数据的文件对象两个实参
json.dump(numbers,f_obj)
#输出结果:终端没有输出,numbers.json文件内容
[2, 3, 5, 6, 8, 10, 15, 26]
#使用json.load()读取数据到内存中
import json
filename = 'numbers.json'
with open(filename) as f_obj:
numbers = json.load(f_obj)
print(numbers)
#输出结果:
[2, 3, 5, 6, 8, 10, 15, 26]
#####################
10.4.2 保存和读取用户生成的数据
#保存用户输入的数据到json文件中
import json
username = input("What is your name :")
filename = 'username.json'
with open(filename,'w') as f_obj:
json.dump(username,f_obj)
print("We'll remember you when you come back, "+ username + "!")
#输出结果:json文件内容为"Abcd";终端输入和输出如下
What is your name :Abcd
We'll remember you when you come back, Abcd!
#以前存储过就加载,否则提示输入,输入后保存
import json
filename = 'username.json'
try:
#如果以前存储了用户名就加载
with open(filename) as f_obj:
username = json.load(f_obj)
#如果以前没有存储过,提示用户输入,然后存储用户输入的数据
except FileNotFoundError:
username = input("What is your name :")
with open(filename,'w') as f_obj:
json.dump(username,f_obj)
print("We'll remember you when you come back, "+ username + "!")
else:
print("Welcome back, " + username +"!")
#输出结果:以前存储过的
Welcome back, Abcd!
#####################
10.4.3 重构
#重构是将代码分为一系列完成具体工作的函数的过程;让代码更清晰,更易于理解和扩展
#重构前
import json
def greet_user():
filename = 'username.json'
try:
#如果以前存储了用户名就加载
with open(filename) as f_obj:
username = json.load(f_obj)
#如果以前没有存储过,提示用户输入,然后存储用户输入的数据
except FileNotFoundError:
username = input("What is your name :")
with open(filename,'w') as f_obj:
json.dump(username,f_obj)
print("We'll remember you when you come back, "+ username + "!")
else:
print("Welcome back, " + username +"!")
greet_user()
#以上greet_user()函数所做的不仅仅是问候,还有获取存储的数据,没有存储还要提示用户输入,下面重构该函数,让greet_user()不做那么多事
#重构后
import json
#定义一个函数加载存储的数据值,如果不存在返回None
def get_stored_username():
filename = 'username.json'
try:
with open(filename)as f_obj:
username = json.load(f_obj)
except FileNotFoundError:
return None
else:
return username
#定义一个函数只获取并存储新用户
def get_new_username():
username = input("What is your name :")
filename = 'username.json'
with open(filename, 'w') as f_obj:
json.dump(username, f_obj)
return username
#问候用户,已存储过的就欢迎回来;新用户就提示
def greet_user():
username = get_stored_username()
if username:
print("Welcome back, " + username +"!")
else:
username = get_new_username()
print("We'll remember you when you come back, "+ username + "!")
greet_user()
#输出结果: 新用户
What is your name :Ef
We'll remember you when you come back, Ef!
其他章节内容:
Python编程从入门到实践基础知识:https://blog.youkuaiyun.com/louzhu_lz/article/details/90721685
Python编程从入门到实践(第三、四章的 列表和元祖):https://blog.youkuaiyun.com/louzhu_lz/article/details/91354506
Python编程从入门到实践(第五章 if语句学习总结):https://blog.youkuaiyun.com/louzhu_lz/article/details/91409903
Python编程从入门到实践(第六章 字典学习总结):https://blog.youkuaiyun.com/louzhu_lz/article/details/91910554
Python编程从入门到实践(第七章 用户输入和while循环学习总结):https://blog.youkuaiyun.com/louzhu_lz/article/details/92384649
Python编程从入门到实践(第八章 函数)学习总结:https://blog.youkuaiyun.com/louzhu_lz/article/details/93377817
Python编程从入门到实践(第九章 类)学习总结:https://blog.youkuaiyun.com/louzhu_lz/article/details/93655674
Python编程从入门到实践(第十章 文件和异常)学习总结:https://blog.youkuaiyun.com/louzhu_lz/article/details/100060189