9、文件和异常
- 如何读取文件
要以任何方式使用文件,哪怕仅仅是打印其内容,都得先打开文件,才能访问它。函数open()接受一个参数:要打开的文件的名称。Python在当前指定的文件所在的目录中查找指定的文件。 关键字with在不再需要访问文件之后将其关闭。我们也可以调用open()和close()来打开和关闭文件,但这样做时,如果程序存在bug导致方法close()未执行,文件将不会关闭。这看似微不足道,但未妥善关闭文件可能导致数据丢失或受损。
因为以下存在文件路径的问题,所以先放一张目录图:
- 读取py文件所在目录下的文件(test.py访问text_in_code.txt):
with open('test_in_code.txt') as file_object:
contents = file_object.read()
print(contents)
输出:
3.1415926535
8979323846
2643383279
直接在路径中写入文件名即可。(vscode打开文件显示找不到文件时,这篇文章可以解决)
- 读取py文件同级文件夹中文件(test.py访问文件夹try中的try.txt):
with open('try/try.txt') as file_object:
contents = file_object.read()
print(contents)
输出:
this is try.txt
要加入相对路径,说明文件夹try,告诉vscode到与py文件同级的try文件夹中寻找。
- 读取与py所在文件夹同级的文件夹中文件(test.py访问data文件夹中的test.py)
with open('../data/test.txt') as file_object:
contents = file_object.read()
print(contents)
输出:
this is text file in data
如代码所示,通过在路径中加 ’ .. ’ 我们可以回到上一级目录,然后再从上一级目录去data文件夹中寻找test.txt文件。通过增加 ’ .. ’ 我们还可以回到更高层的目录。 当相对路径无法确定是否正确时,可以使用绝对路径,将路径字符串存储在一个变量中,传进open()函数,使用绝对路径可以访问任何文件。
- 逐行读取
读取文件时,常常需要检查其中的每一行:可能要在文件中查找特定的信息,或者要以某种方式修改文件中的文本。
path = '../data/test.txt'
with open(path) as file_object:
for line in file_object:
print(line.rstrip())
输出:
3.1415926535
8979323846
2643383279
在文件中,每一行的末尾都有一个看不见的换行符,如果不加rstrip()函数,在输出的结果我们会看到每行数字之间有一个空行。这是因为在print()语句结束时有一个换行,文本本身又有一个换行。
- 创建一个包含文件各行内容的列表
使用关键字with时,open()返回的文件对象只在with代码块内可用。如果要在with代码块外访问文件的内容,可在with代码块内将文件的各行存储在一个列表中,并在with代码块外使用该列表:可以立即处理文件的各个部分,也可以推迟到程序后面再处理。
path = '../data/test.txt'
with open(path) as file_object:
lines = file_object.readlines()
print(lines)
输出:
['3.1415926535\n', ' 8979323846\n', ' 2643383279']
(可见,文本每一行的结尾都是有一个换行符的。)
注意,读文本文件时,Python将其中所有的文本都解读为字符串。如果读取的是数,并要将其作为数值使用,就必须使用函数int()将其转换为整数或使用函数float()将其转换为浮点数。
- 写入文件
要将文本写入文件,在调用open()时需要提供另一个实参(第一个说明文件路径和文件名,第二个说明访问方式;还可以包含第三个参数encoding = ‘utf-8’,这个参数在系统的默认编码与要读取文件使用的编码不一致时,必须添加。),告诉Python你要以什么模式打开文件:
参数 | 名称 | 说明 |
---|
w | 写入模式 | 可以对文件进行写操作,第二次写会将第一次写的抹掉 | r | 读取模式 | 在这个模式只可以读文件 | a | 附加模式 | 与写模式不同,不会抹掉之前文字,在文本最后添加文字 | r+ | 读写模式 | 可以同时进行读写 |
当我们以写入和附加模式打开文件时,如果该文件本来不存在,那么就会为我们创建一个文件。
- 异常
每当发生让Python不知所措的错误时,它都会创建一个异常。如果我们编写了处理该异常的代码,程序将继续运行;如果未对异常进行处理,程序将停止并显示traceback,其中包含有关异常的报告。 我们可以用tey-except代码块处理异常。使用try-except代码块时,即便出现异常,程序也将继续运行:显示我们编写的友好的错误消息,而不是令用户迷惑的traceback。
try:
print(5/0)
except ZeroDivisionError:
print("You can not divide by zero!")
输出:
You can not divide by zero!
- else代码块
Python尝试执行try代码块中的代码,只有可能引发异常的代码才需要放在try语句中,有时候,有一些仅在try代码块成功执行时才需要运行的代码,这些代码放在else代码块中。except代码块告诉Python,如果尝试运行try代码块中的代码时引发了异常该怎么办。
try:
answer = a/b
except ZeroDivisionError:
print("You can not divide by zero!")
else:
print(answer)
(如果b是0,则会执行except代码块,否则执行else代码块)
- 静默失败
并不是每次捕获到异常都需要告诉用户,有时候你希望程序在发生异常时保持静默,就像什么都没有发生一样继续运行。这是可以在except代码块中用pass语句。pass告诉Python什么都不要做,而且充当了占位符,提醒现在什么都没做,后面可能会修改。 什么时候应该静默失败需要考经验来判断,通常情况下,需要报告给用户的异常大多是用户可以处理或可采取进一步措施的。 - 存储数据
用户关闭程序是,几乎总是要保存他们提供的信息。一种简单的方式是使用模块json来存储数据。 模块json让我们能够将简单的Python数据结构转存到文件中,并在程序再次运行时加载该文件中的数据。我们还可以使用json在Python程序之间分享数据。而且,json格式并非是Python专用的,这使得我们能够以JSON格式存储的数据与使用其他编程语言的人分享。 使用json要引入json模块,可以使用json中的dump()函数存储数据,load()函数家在数据。 dump(): 第一个参数是要存储的数据,第二个参数是用于存储数据的文件对象。
import json
numbers = list(range(10))
filename = "../data/numbers.json"
with open(filename,'w') as f:
json.dump(numbers, f)
输出:
import json
filename = "../data/numbers.json"
with open(filename,'r') as f:
numbers = json.load(f)
print(numbers)
输出:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|