文章目录
- 文件和异常
- 从文件中读取数据
- 读取整个文件
- 文件路径
- 逐行读取
- 创建一个包含文件各行内容的列表
- 使用文件的内容
- 包含一百万位的大型文件
- 圆周率值中包含你的生日吗
- 写入文件
- 写入空文件
- 写入多行
- 附加到文件
- 异常
- 处理 ZeroDivisionError异常
- 使用 try-except 代码块
- 使用异常避免崩溃
- else 代码块
- 处理 FileNotFoundError异常
- Python无法读取不存在的文件,因此它引发一个异常。
- 查找的文件可能在其他地方,可使用 try-except 代码块以直观的方式处理。
- 分析文本
- 使用多个文件
- 静默失败
- 决定报告哪些错误
- 存储数据
- 使用 json.dump()和 json.load()
- 保存和读取用户生成的数据
- 重构
文件和异常
从文件中读取数据
读取整个文件
要读取文件,需要一个包含几行文本的文件
原始文件pi_digits.txt,新建file_reader.py:
with open('pi_digits.txt') as file_object:
centents = file_object.read()
print(centents.strip())
3.1415926535
8979323846
2643383279
文件路径
- 将类似于 pi_digits.txt 的文件名传递给函数open()时,Python 将在当前执行的文件(即file_reader.py)所在的目录中查找。
- 打开非同一目录文件,可使用相对路径,而该位置时相对于当前运行的程序所在的目录的。
- 显示路径文件时,windows系统使用反斜杠(\),但是代码中依然可以使用斜杠(/)。
- 还可以将文件在计算机中的准确位置告诉Python,这叫绝对路径。绝对路径比相对路径长,因此将其赋给一个变量,再将该变量传递给open()。
- 最简单的做法是,要么将数据文件存储在程序文件所在的目录,要么将其存储在程序文件所在目录下的一个文件夹中。
- 如果在文件路径中直接使用反斜杠 “D:\pythonProject\study\little_women.txt”,可对路径中的每个反斜杠都进行转义。如
"D:\\pythonProject\\study\\little_women.txt"
逐行读取
要以每次一行的方式检查文件,可对文件对象使用 for 循环。
filename = 'pi_digits.txt'
with open(filename) as file_object: #默认 mode='r'
for line in file_object:
print(line.rstrip())
3.1415926535
8979323846
2643383279
with open('pi_digits.txt',mode='r') as f:
for line in f:
print(line.rstrip())
3.1415926535
8979323846
2643383279
创建一个包含文件各行内容的列表
使用关键字 with 时,open()返回的文件对象只在 with 代码块内可用。如果要在with代码块外访问文件的内容,可在 with 代码块内将文件的各行存储在一个列表中。
filename = 'pi_digits.txt'
with open(filename) as file_object:
lines = file_object.readlines()
for line in lines:
print(line.rstrip())
3.1415926535
8979323846
2643383279
filename = 'pi_digits.txt'
with open(filename) as file_object:
lines = file_object.readlines()
#方法readlines() 从文件中读取每一行,并将其存储在一个列表中;该列表被赋给变量lines。
print(lines)
['3.1415926535 \n', ' 8979323846 \n', ' 2643383279\n']
使用文件的内容
将文件读取到内存中后,就能以任何方式使用这些数据了。
读取文本时,Python将其中的所有文本都解读为字符串。如果读取的是数,并要将其作文数值使用,就必须使用函数int()将其转换为整数或使用函数float()将其转换为浮点数。
filename = 'pi_digits.txt'
with open(filename) as file_object:
lines = file_object.readlines()
pi_string = ''
for line in lines:
pi_string += line.strip()
print(pi_string)
print(len(pi_string))
3.141592653589793238462643383279
32
包含一百万位的大型文件
创建一个包含所有这些数字的字符串,将这个文件传递给它
filename = 'pi_million_digits.txt'
with open(filename) as file_object:
lines = file_object.readlines()
pi_string = ''
for line in lines:
pi_string += line.strip()
print(f'{pi_string[:52]}...')
print(len(pi_string))
3.14159265358979323846264338327950288419716939937510...
1000002
圆周率值中包含你的生日吗
将生日表示为一个由数字组成的字符串,再检查这个字符串是否包含在 pi_string 中
filename = 'pi_million_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 million digits of pi!')
else:
print('Your birthday does not appear in the million digits of pi.')
Enter your birthday,in the form mmddyy: 100149
Your birthday appears in the million digits of pi!
写入文件
写入空文件
相比于计算机中的其他文件,这个文件没有什么不同。
读取模式 r(默认) , 写入模式 w(存在则先清空再写), 附加模式 a, 读写模式 r+
Python只能将字符串写入文本文件。要将数值数据存储到文本文件中,必须先使用函数str()j将其转换为字符串格式。
写入多行
函数 write()不会在写入的文本末尾添加换行符
,因此写入多行时需要指定换行符。
filename = 'programming.txt'
with open(filename, 'w') as file_object:
file_object.write("I love programming.\n")
file_object.write("I love creating new games.\n")
#生成了一个programming.txt,内容如下:
I love programming.
I love creating new games.
附加到文件
如果要给文件添加内容,而不是覆盖原有的内容,可以以附加模式打开文件。
filename = 'programming.txt'
with open(filename, 'a') as file_object:
file_object.write("I also love finding meaning in large datasets.\n")
file_object.write("I love creating apps that can run in a browser.\n")
更新后的programming.txt,内容如下:
I love programming.
I love creating new games.
I also love finding meaning in large datasets. #追加模式下写的
I love creating apps that can run in a browser. #追加模式下写的
异常
Python使用称为异常的特殊对象来管理程序执行期间发生的错误。每当发生让Python不知所措的错误时,它都会创建一个异常对象。如果你现象了处理该异常的代码,程序将继续运行,如果未对异常进行处理,程序将停止并显示traceback,其中包含有关异常的表格。
异常是使用try-except代码块处理的。
处理 ZeroDivisionError异常
不能用数除以 0。
使用 try-except 代码块
当你认为可能会发生错误时,可编写一个 try-except 代码块来处理可能引发的异常。
如果try代码块中的代码运行起来没有问题,Python将跳过except代码块;如果try代码块中的代码导致了错误,Python将查找与之匹配的except代码块并运行其中的代码。
如果 try-except 代码块后面还有其他代码,程序将接着运行。
try:
print(5/0)
except ZeroDivisionError:
print("You can't dicide by zero!")
You can't dicide by zero!
使用异常避免崩溃
发生错误时,如果程序还有工作尚未完成,妥善地处理错误就尤其重要。
print("Give me two numbers, and I'll divide them.")
print("Enter 'q' to quit.")
while True:
first_number = input("\nFirst number: ")
if first_number == 'q':
break
second_number = input("Second number: ")
if second_number == 'q':
break
answer = int(first_number) / int(second_number)
print(answer)
Give me two numbers, and I'll divide them.
Enter 'q' to quit.
First number: 3
Second number: 0
Traceback (most recent call last):
File "D:\pythonProject\study\division_calculator.py", line 29, in <module>
answer = int(first_number) / int(second_number)
ZeroDivisionError: division by zero
else 代码块
通过将可能引发错误的代码块放在try-except代码块
中,可提高程序抵御错误的能力。
有一些仅在 try 代码块成功
执行时才需要运行的代码,这些代码应放在 else 代码块
中。
print("Give me two numbers, and I'll divide them.")
print("Enter 'q' to quit.")
while True:
first_number = input("\nFirst number: ")
if first_number == 'q':
break
second_number = input("Second number: ")
if second_number == 'q':
break
try:
answer = int(first_number) / int(second_number)
except ZeroDivisionError:
print("You can't divide by 0!")
else:
print(answer)
Give me two numbers, and I'll divide them.
Enter 'q' to quit.
First number: 5
Second number: 0
You can't divide by 0!
First number: 4
Second number: 2
2.0
处理 FileNotFoundError异常
Python无法读取不存在的文件,因此它引发一个异常。
filename = 'alice.txt'
with open(filename, encoding='utf-8') as f:
contents = f.read()
raceback (most recent call last):
File "D:\pythonProject\study\alice.py", line 3, in <module>
with open(filename, encoding='utf-8') as f:
FileNotFoundError: [Errno 2] No such file or directory: 'alice.txt'
查找的文件可能在其他地方,可使用 try-except 代码块以直观的方式处理。
filename = 'alice.txt'
try:
with open(filename, encoding='utf-8') as f:
contents = f.read()
except FileNotFoundError:
print(f"Sorry, the file {filename} does not exist.")
else:
# Count the approximate number of words in the file.
words = contents.split()
num_words = len(words)
print(f"The file {filename} has about {num_words} words.")
Sorry, the file alice.txt does not exist.
分析文本
方法split()以空格为分隔符将字符串拆分成多个部分,并将这些部分都存储到一个列表中,结果是一个报告字符串中所有单词的列表,虽然有些单词可能包含标点。
对整篇小说调用 split(),再计算得到的列表包含多少个元素,从而确定整篇童话大致包含多少个单词。
filename = 'alice.txt'
try:
with open(filename, encoding='utf-8') as f:
contents = f.read()
except FileNotFoundError:
print(f"Sorry, the file {filename} does not exist.")
else:
# Count the approximate number of words in the file.
words = contents.split()
num_words = len(words)
print(f"The file {filename} has about {num_words} words.")
The file alice.txt has about 29465 words.
使用多个文件
编写一个简单的循环,计算要分析的任何文本包含多少个单词。
def count_words(filename):
"""计算一个文件大致包含多少个单词"""
try:
with open(filename, encoding='utf-8') as f:
contents = f.read()
except FileNotFoundError:
print(f"Sorry, the file {filename} does not exist.")
else:
words = contents.split()
num_words = len(words)
print(f"The file {filename} has about {num_words} words.")
filename = 'alice.txt'
count_words(filename)
def count_words(filename):
"""计算一个文件大致包含多少个单词"""
try:
with open(filename, encoding='utf-8') as f:
contents = f.read()
except FileNotFoundError:
print(f"Sorry, the file {filename} does not exist.")
else:
words = contents.split()
num_words = len(words)
print(f"The file {filename} has about {num_words} words.")
filenames = ['alice.txt','siddhartha.txt','moby_dick.txt','little_women.txt']
for filename in filenames:
count_words(filename)
The file alice.txt has about 29465 words.
Sorry, the file siddhartha.txt does not exist.
The file moby_dick.txt has about 215830 words.
The file little_women.txt has about 189079 words.
静默失败
Python有一个 pass 语句,可用于让 Python 在代码块中什么都不要做。
pass 语句充当占位符,提醒你在程序的某个地方什么都没有做,并且也行以后要在这里做些什么。
def count_words(filename):
"""计算一个文件大致包含多少个单词"""
try:
with open(filename, encoding='utf-8') as f:
contents = f.read()
except FileNotFoundError:
pass
else:
words = contents.split()
num_words = len(words)
print(f"The file {filename} has about {num_words} words.")
filenames = ['alice.txt','siddhartha.txt','moby_dick.txt','little_women.txt']
for filename in filenames:
count_words(filename)
The file alice.txt has about 29465 words.
The file moby_dick.txt has about 215830 words.
The file little_women.txt has about 189079 words.
决定报告哪些错误
凭借经验可判断该在程序的什么地方包含异常处理块,以及出现错误时该向用户提供多少相关的信息。
存储数据
模块json将简单的Python数据结构转储到文件中,并在程序再次运行时加载该文件中的数据。
JSON(JavaScript Object Natation) 格式最初是为JavaScript 开发的,但随后成了一种常见格式,被包括Python在内的众多语音采用。
使用 json.dump()和 json.load()
这是一种在程序之间共享数据的简单方式
import json
numbers = [2, 3, 5, 7, 11, 13]
filename = 'numbers.json'
with open(filename, 'w') as f:
json.dump(numbers, f)
import json
filename = 'numbers.json'
with open(filename) as f:
numbers = json.load(f)
print(numbers)
[2, 3, 5, 7, 11, 13]
保存和读取用户生成的数据
使用 json 保存用户生成的数据
import json
username = input("What is your name? ")
filename = "username.json" #行3可以与行2互换,不影响
with open(filename,"w") as f:
json.dump(username,f)
print(f"We'll remember you when you come back,{username}!")
What is your name? Alice
We'll remember you when you come back,Alice!
import json
filename = 'username.json'
with open(filename) as f:
username = json.load(f)
print(f"Welcome back, {username}!")
Welcome back, Alice!
将以上2个程序合并到一个程序
import json
#如果以前存储了用户名,就加载它
#否则,提示用户输入用户名并存储它
filename = 'username.json'
try:
with open(filename) as f:
username = json.load(f)
except:
username = input("What is your name? ")
with open(filename, "w") as f:
json.dump(username,f)
print(f"We'll remember you when you come back,{username}!")
else:
print(f"Welcome back, {username}!")
Welcome back, Alice!
重构
代码能够正确地运行,但通过将其划分为一系列完成具体工作的函数,还可以改进,这样的过程叫重构。
重构让代码更清晰、更易于理解、更容易扩展。
调用greet_user(),它打印一条合适的信息:要么欢迎老用户回来,要么问候新用户。
它首先调用get_stored_username(),该函数只负责获取已存储的用户名(如果存储了的话)。
最后调用get_new_username(),该函数只负责获取并存储新用户的用户名。
import json
def get_stored_username():
"""Get stored username if available."""
"""如果存储了用户名,就获取它"""
filename = 'username.json'
try:
with open(filename) as f:
username = json.load(f)
except FileNotFoundError:
return None
else:
return username
def get_new_username():
"""Prompt for a new username."""
"""提示用户输入用户名"""
username = input("What is your name? ")
filename = 'username.json'
with open(filename, 'w') as f:
json.dump(username, f)
return username
def greet_user():
"""Greet the user by name."""
"""问候用户,并指出其名字"""
username = get_stored_username()
if username:
print(f"Welcome back, {username}!")
else:
username = get_new_username()
print(f"We'll remember you when you come back, {username}!")
greet_user()