9.文件和异常--《Python编程:从入门到实践》
9.1 从文件中读取数据
要使用文本文件中的信息,首先需要将信息读取到内存中。为此,你可以一次性读取文件的全部内容,也可以以每次一行的方式逐步读取。
9.1.1 读取整个文件
with open('pi_digits.txt') as file_object:
contents = file_object.read()
print(contents)
函数open()接受一个参数:要打开的文件的名称或者路径。它返回一个表示文件的对象。
关键字with在不再需要访问文件后将其关闭。你也可以调用open()和close()来打开和关闭文件。
相比于原始文件,该输出唯一不同的地方是末尾多了一个空行。为何会多出这个空行呢?因为read()到达文件末尾时返回一个空字符串,而将这个空字符串显示出来时就是一个空行。要删除空行,可在print语句中使用rstrip():
print(contents.rstrip())
路径在 Linux 和 Windows 下并不相同。在Linux和OS X中,你可以这样编写代码:
with open('text_files/filename.txt') as file_object:
在Windows系统中,在文件路径中使用反斜杠(\)而不是斜杠(/):
with open('text_files\filename.txt') as file_object:
相对路径:由于文件夹text_files位于文件夹python_work中,因此可使用相对文件路径来打开该文件夹中的文件。相对文件路径让Python到指定的位置去查找,而该位置是相对于当前运行的程序所在目录的。
绝对路径:我们还可以将文件在计算机中的准确位置告诉Python,这样就不用关心当前运行的程序存储在什么地方了。
9.1.2 逐行读取
读取文件时,常常需要检查其中的每一行:你可能要在文件中查找特定的信息,或者要以某种方式修改文件中的文本。
file_path = 'C:\\Users\\sunzhicheng1\\PycharmProjects\\pythonProject1\\pi_digits.txt'
with open(file_path) as file_object:
for line in file_object:
print(line)
"""
3.1415926535
8979323846
2643383279
"""
结果发现空白行变多了,这是因为在这个文件中,每行的末尾都有一个看不见的换行符,而print语句也会加上一个换行符,因此每行末尾都有两个换行符:一个来自文件,另一个来自print语句。要消除这些多余的空白行,可在print语句中使用 rstrip() :
print(line.rstrip())
9.1.3 创建一个包含文件各行内容的列表
readlines() 从文件中读取每一行,并将其存储在一个列表中。
filename = 'pi_digits.txt'
with open(filename) as file_object:
lines = file_object.readlines()
for line in lines:
print(line.rstrip())
9.2 写入文件
调用open()时提供了两个实参。第一个实参也是要打开的文件的名称,第二个实参表示以怎样的方式打开这个文件。打开文件时,可指定读取模
式('r')、写入模式('w')、附加模式('a')或让你能够读取和写入文件的模式('r+')。如果省略,则为只读模式打开。
如果你要写入的文件不存在,函数open()将自动创建它。以写入('w')模式打开文件时千万要小心,因为如果指定的文件已经存在,Python将在返回文件对象前清空该文件。
函数 write() 不会在你写入的文本末尾添加换行符,因此如果我们没有自己写入\n,就会导致内容写入到一行上。
注意:Python只能将字符串写入文本文件。要将数值数据存储到文本文件中,必须先使用函数 str() 将数值数据转换为字符串格式。
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")
9.2.1 附加到文件
如果你要给文件添加内容,而不是覆盖原有的内容,可以附加模式(a)打开文件。Python不会在返回文件对象前清空文件,而写入到文件的行都将添加到文件末尾。
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")
9.3 异常
每当发生让Python不知所措的错误时,它都会创建一个异常对象。如果你编写了处理该异常的代码,程序将继续运行;如果你未对异常进行处理,程序将停止,并显示一个traceback,其中包含有关异常的报告。
异常是使用try-except代码块处理的。
9.3.1 使用 try-except 代码块
这里使用 ZeroDivisionError 异常作为例子,这个异常是指不能将将一个数除以0。
程序自动处理异常时显示的traceback:
Traceback (most recent call last):
File "division.py", line 1, in <module>
print(5/0)
ZeroDivisionError: division by zero
使用 try-except 代码块处理 ZeroDivisionError 异常:
try:
print(5/0)
except ZeroDivisionError:
print("You can't divide by zero!")
9.3.2 else 代码块
通过将可能引发错误的代码放在try-except代码块中,可提高这个程序抵御错误的能力。这个示例还包含一个else代码块;依赖于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: ")
try:
answer = int(first_number) / int(second_number)
except ZeroDivisionError:
print("You can't divide by 0!")
else:
print(answer)
9.4 存储数据
模块 json 让你能够将简单的 Python 数据结构转储到文件中,并在程序再次运行时加载该文件中的数据。
9.4.1 使用 json.dump()和 json.load()
将使用 json.dump() 来存储这组数字,而将使用 json.load() 来读取数字。
写入 json 文件内容:
import json
numbers = [2, 3, 5, 7, 11, 13]
# 写入 json 文件
filename = 'numbers.json'
with open(filename, 'w') as f_obj:
json.dump(numbers, f_obj)
json 文件内容:
[2, 3, 5, 7, 11, 13]
读取 json 文件内容:
# 读取 json 文件内容
import json
filename = 'numbers.json'
with open(filename) as f_obj:
numbers = json.load(f_obj)
print(numbers)