《python编程:入门到实践》第十章 文件和异常

10.1 从文件读取数据

要使用文本文件中的信息,首先需要将信息读取到内存中。为此,你可以一次性读取文件的全部内容,也可以以每次一行的方式逐步读取。
10.1.1 读取整个文件
with open('pi_digits.txt') as file_object:
 contents = file_object.read() 
print(contents)
在这个程序中,第 1 行代码做了大量的工作。我们先来看看函数 open() 函数open() 接受一个参数:要打开的文件的名称。Python 在当前执行的文件所在的目录中查找指定的文件(如需打开其他位置文件请参考10.1.2)在这个示例中, Python 当前所运行的程序 所在的目录中 查找 pi_digits.txt  。函数 open() 返回一个表示文件的对象。在这里, open('pi_digits.txt') 返回一个表示文件 pi_digits.txt 的对象; Python 将这个对象存储在我们将 在后面使用的变量中。
关键字 with 在不再需要访问文件后将其关闭。在这个程序中,注意到我们调用了 open() ,但没有调用 close() ;你也可以调用 open() close() 来打开和关闭文件,但 这样做时,如果程序存在bug ,导致 close() 语句未执行,文件将不会关闭。这看似微不足道,但未妥善地关闭文件可能会导致数据丢失或受损。如果在程序中过早地调 用close() ,你会发现需要使用文件时它已关闭 (无法访问),这会导致更多的错误。并非在任何情况下都能轻松确定关闭文件的恰当时机,但通过使用前面所示的结构,可让Python 去确定:你只管打开文件,并在需要时使用它, Python 自会在合适的时候自动将其关闭。
需注意pi_digits.txt中的内容是英文和数字,还是使用的中文。如果使用了中文,我们需要注意编码格式,一般文本文档的编码格式会是utf-8,则需将第一行代码修改为:
with open('poem.txt',encoding='utf-8') as file_object:

编码格式查看位置(在右下角写了个utf-8):

 如需修改可将文件‘另存为’并修改:

 输出结果如下:

 大家自己打好代码便可观察发现,相比于原始文件,该输出唯一不同的地方是末尾多了一行。

为何会多出这个空行呢?因为read() 到达文件末尾时返回一个空字符串,而将这个空字符串显示出来时就是一个空行。要删除多出来的空行,可在print 语句中使用rstrip()

print(contents.rstrip())
10.1.2 文件路径
Windows 系统中,在文件路径中使用反斜杠( \ )而不是斜杠( / ):
file_path = 'C:\Users\ehmatthes\other_files\text_files\filename.txt'
with open(file_path) as file_object:
绝对路径通常比相对路径更长,因此将其存储在一个变量中。(这里只介绍了绝对路径,还有一个相对路径可以自行了解)
10.1.3 逐行读取

读取文件时,你可能要在文件中查找特定的信息,或者要以某种方式修改文件中的文本。
例如,你可能要遍历一个包含天气数据的文件,并使用天气描述中包含字样sunny 的行。在新闻报道中,你可能会查找包含标签 <headline> 的行,并按特定的格式设置它。
要以每次一行的方式检查文件,可对文件对象使用 for 循环:
with open('poem.txt',encoding='utf-8') as file_object:
 for line in file_object: 
  print(line)

结果如下:

观察结果我们会发现:我们每打印一行,还多了一行空白行。

因为在这个文件中,每行的末尾都有一个看不见的换行符,而print 语句也会加上一个换行符。。要消除这些多余的空白行,可在print 语句中使用rstrip()

with open('poem.txt',encoding='utf-8') as file_object:
 for line in file_object:
  print(line.rstrip())

  输出结果如下:

注意:还有一种删除方法叫strip()。strip()和rstrip()都是字符串的方法,用于删除字符串开头或结尾的特定字符(默认为空格)。strip()方法会同时删除字符串开头和结尾的特定字符。rstrip()方法只会删除字符串结尾的特定字符。

10.1.4 创建一个包含文件各行内容的列表
使用关键字 with 时, open() 返回的文件对象只在 with 代码块内可用。如果要在  with 代码块外访问文件的内容,可在  with 代码块内将文件的各行存储在一个列表中,即可在 with 代码块外使用该列表。
with open(filename) as file_object: 
 lines = file_object.readlines()

for line in lines: 
 print(line.rstrip())
该列表被存储到变量 lines 中;在 with 代码块外,我们依然可以使用这个变量。由于列表 lines 的每个元素都对应于文件中的一行,因此输出与文件内容完全一致。

注意:读取文本文件时,Python将其中的所有文本都解读为字符串。如果你读取的是数字,并要将其作为数值使用,就必须使用函数int() 将其转换为整数,或使用

函数 float() 将其转换为浮点数。
10.1.5 大型文件之“圆周率中包含你的生日吗?”
前面分析的代码只有几行,但实际它们的功能不止于此,如果我们有一个文本文件,其中包含精确到小数点后1 000 000位而不是30位的圆周率值,也可创建一个包含所有这些数字的字符串。为此,我们无需对前面的程序做任何修改,只需将这个文件传递给它即可。
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(pi_string[:52] + "...")
#我们只打印到小数点后50位,以免终端为显示全部1 000 000位而不断地翻滚
print(len(pi_string))
#输出表明,我们创建的字符串确实包含精确到小数点后1 000 000位的圆周率值

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.")

10.2 写入文件

之前我们学习了怎么读文件,现在我们学习写入文件,这也是保存数据最简单的方式之一。

10.2.1 写入空文件
filename = 'programming.txt'
with open(filename, 'w') as file_object:
 file_object.write("I love programming.")

 调用open() 时提供了两个实参,第一个实参也是要打开的文件的名称;第二个实参('w' )告诉Python,我们要以写入模式打开这个文件。

可指定读取模式('r' )、写入模式('w' )、附加模式('a' )或让你能够读取和写入文件的模式('r+' )。如果你省略了模式实参,Python将以默认的只读模式打开文件。
注意:如果你要写入的文件不存在,函数open() 将自动创建它。然而,以写入('w' )模式打开文件时千万要小心,因为如果指定的文件已经存在,Python将在返回文件对象前清空
该文件。
注意 :Python只能将字符串写入文本文件。要将数值数据存储到文本文件中,必须先使用函数 str() 将其转换为字符串格式。
函数 write() 不会在你写入的文本末尾添加换行符,因此如果需要写入多行时,需要在 write() 语句中包含换行符。

10.3 异常

每当发生让 Python 不知所措的错误时,它都会创建一个异常对象。如果你编写了处理该异常的代码,程序将继 续运行;如果你未对异常进行处理,程序将停止,并显示一个traceback ,其中包含有关异常的报告。
10.3.1 使用 try-except 代码块
当你认为某部分代码可能发生错误时,可编写一个 try-except 代码块来处理可能引发的异常。
例如:
try:
 print(5/0)
except ZeroDivisionError:
 print("You can't divide by zero!")
我们将导致错误的代码行 print(5/0) 放在了一个 try 代码块中。如果 try 代码块中的代码运行起来没有问题, Python 将跳过 except 代码块;如果 try 代码块中的代码导致了错误,Python 将查找这样的 except 代码块,并运行其中的代码,即其中指定的错误与引发的错误相同。
在这个示例中, try 代码块中的代码引发了 ZeroDivisionError 异常,因此 Python 指出了该如何解决问题的 except 代码块,并运行其中的代码。
当然,如果希望在发生异常时选择一声不吭,我们可以在except代码块中使用pass语句,
来让 Python 什么都不要做。
except ZeroDivisionError:
 print("You can't divide by zero!")
10.3.2 else代码块
try-except-else 代码块的工作原理大致如下: Python 尝试执行  try 代码块中的代码;只有可能引发异常的代码才需要放在  try 语句中。有时候,有一些仅在  try 代码块成功执行时才需要运行的代码,应放在 else 代码块中。 except 代码块告诉 Python ,如果它尝试运行 try 代码块中的代码时引发了指定的异常,就怎么办。
通过预测可能发生错误的代码,可编写健壮的程序,它们即便面临无效数据或缺少资源,也能继续运行,从而能够抵御无意的用户错误和恶意的攻击。
例如:
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)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橙雨敲代码ing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值