《Python编程:从入门到实战》(第2版)学习笔记 第10章 文件和异常(上)

【写在前面】为进一步提高自己的python代码能力,打算把几本经典书籍重新过一遍,形成系统的知识体系,同时适当记录一些学习笔记,我尽量及时更新!先从经典的《Python编程:从入门到实战》书籍开始吧。有问题欢迎在评论区讨论,互相学习,good good study,day day up!上一章《Python编程:从入门到实战》(第2版)学习笔记 第9章 类介绍了类,这章介绍文件和异常【分为上和下两篇】

【特别说明】这是第二版的《Python编程:从入门到实战》,书本的Python版本是3.7.2,我自己运行代码的环境是3.7.0,不同Python版本的功能不同。

至此,你掌握了编写组织有序、易于使用的程序所需的基本技能,该考虑让程序目标更明确、用途更大。在本章你将学习

  1. 处理文件,让程序能够快速地分析大量数据;
  2. 错误处理,避免程序在面对意外情形时崩溃;
  3. 异常 ,它是Python创建的特殊对象,用于管理程序运行时出现的错误;
  4. 模块json ,它能够保存用户数据,以免在程序停止运行后丢失。

学习处理文件和保存数据可让你的程序使用起来更容易:用户将能够选择输入什么样的数据,以及何时输入。学习处理异常可帮助你应对文件不存在的情形,以及处理其他可能导致程序崩溃的问题。这让你的程序在面对错误的数据时更健壮。本章的学习可提高程序的适用性、可用性和稳定性。

10.1 从文件中读取数据

文本文件可存储的数据量很多:天气数据、交通数据、社会经济数据、文学作品等。每当需要分析或修改存储在文件中的信息时,读取文件都很有用。将信息读取到内存中有两种方式:一次性读取文件的全部内容;以每次一行的方式逐步读取。

10.1.1 读取整个文件

要读取文件,需要一个包含几行文本的文件。首先创建一个文件,它包含精确到小数点后30位的圆周率值,且在小数点后每10位处换行(可在ituring.cn/book/2784下载该文件):

pi_digits.txt
3.1415926535
8979323846
2643383279

下面打开并读取这个文件,将其内容显示到屏幕上:

file_reader.py

>>> with open('pi_digits.txt') as file_object:
>>>         contents = file_object.read()
>>> print(contents)

第一行代码很重要,首先打开文件。函数open() 接受一个参数:要打开文件的名称。Python在当前执行的文件所在的目录中查找指定的文件。函数open() 返回一个表示文件的对象,将该对象赋给file_object 供以后使用。关键字with 在不再需要访问文件后将其关闭。

注意我们调用了open() ,但没有调用close() ;也可以同时调用,但如果程序存在bug导致close() 未执行,文件将不会关闭。这看似微不足道,但未妥善关闭文件可能导致数据丢失或受损。在程序中过早调用close() ,导致需要使用文件时它已关闭 (无法访问),将报错。并非在任何情况下都能轻松确定关闭文件的恰当时机,但通过使用前面所示的结构,可做到:只管打开文件,并在需要时使用它,Python会在合适的时候自动关闭。

方法read() 读取这个文件的全部内容,并将其作为一个长长的字符串赋给变量contents 。通过打印contents 的值,输出如下:

3.1415926535
8979323846
2643383279
 

相比于原始文件,该输出在末尾多了一个空行。为何?因为read() 到达文件末尾时返回一个空字符串【 len(s) ==0  则字符串为空,而将这个空字符串显示出来时就是一个空行。要删除多出来的空行,可在调用print() 中使用rstrip() 删除字符串末尾的空白:

>>> with open('pi_digits.txt') as file_object:
>>>         contents = file_object.read()
>>> print(contents.rstrip())

现在,输出与原始文件完全相同:
3.1415926535
8979323846
2643383279

10.1.2 文件路径

如果需要打开不与.py程序文件位于同一个目录中的文件,需要提供文件路径。

这里文件夹text_files位于文件夹python_work中,可以使用相对文件路径。例如:with open('text_files/filename.txt') as file_object:让Python到文件夹python_work下的文件夹text_files中去查找指定的.txt文件。

注意 显示文件路径时,Windows系统使用反斜杠(\)而不是斜杠(/)。

还能将文件在计算机中的准确位置告诉Python,这称绝对文件路径。在相对路径行不通时,可使用绝对路径。绝对路径通常比相对路径更长一点:

>>> file_path = '/home/ehmatthes/other_files/text_files/_filename_.txt'
>>> with open(file_path) as file_object:

注意 如果在文件路径中直接使用反斜杠,将引发错误,因为反斜杠用于对字符串中的字符进行转义。例如,"C:\path\to\file.txt" 的\t 将被解读为制表符。如果一定要使用反斜杠,可对路径中的每个反斜杠都进行转义,如"C:\\path\\to\\file.txt"。

10.1.3 逐行读取

读取文件时,常需要检查其中的每一行:可能要在文件中查找特定信息或修改文件中的文本。可对文件对象使用for 循环:

file_reader.py

>>> filename = 'pi_digits.txt'
>>> with open(filename) as file_object:
>>>         for line in file_object:
>>>                 print(line)

第一行将要读取文件的名称赋给变量filename,它表示的并非实际文件——它只是字符串。第二行调用open() ,将一个表示文件及其内容的对象赋给了变量file_object。使用关键字with让python妥善地打开和关闭文件。

打印每一行时,发现空白行更多了:
3.1415926535

8979323846

2643383279

为何?因为每行的末尾都有一个看不见的换行符,而函数调用print() 也会加上一个换行符,因此每行末尾都有两个换行符:一个来自文件,另一个来自函数调用print() 。要消除多余的空白行,可在函数调用print() 中使用rstrip() :print(line.rstrip())

则输出与文件内容完全相同:

3.1415926535
8979323846
2643383279

10.1.4 创建一个包含文件各行内容的列表

使用关键字with 时,open() 返回的文件对象只在with代码块内可用。要在with代码块外访问文件的内容,可在with代码块内将文件的各行存储在列表中。

下面的示例在with 代码块中将文件pi_digits.txt的各行存储在一个列表中,再在with代码块外打印:

>>> filename = 'pi_digits.txt'
>>> with open(filename) as file_object:
>>>         lines = file_object.readlines()
>>> for line in lines:
>>>         print(line.rstrip())  #输出与文件内容完全一致

方法readlines() 从文件中读取每一行,并将其存储在一个列表中,该列表被赋给变量lines 。在with 代码块外可使用这个变量。

10.1.5 使用文件的内容

将文件读取到内存中后,能以任何方式使用这些数据。

pi_string.py

>>> filename = 'pi_digits.txt'
>>> with open(filename) as file_object:
>>>         lines = file_object.readlines()
>>> pi_string = '' #创建一个字符串
>>> for line in lines:  #使用循环将各行加入pi_string,并删除每行末尾的换行符
>>>         pi_string += line.rstrip()
>>> print(pi_string)
>>> print(len(pi_string))

打印这个字符串及其长度:

3.1415926535 8979323846 2643383279
36

上面在删除空格时,使用的rstrip()而非strip(),若使用line.strip(),则输出为:

3.141592653589793238462643383279
32

注意 读取文本文件时,Python将其中的所有文本都解读为字符串。如果读取的是数,就必须使用函数int() 将其转换为整数函数float() 将其转换为浮点数

10.1.6 包含一百万位的大型文件

前面分析的代码示例也可处理大得多的文件。这里,只打印到小数点后50位,以免终端为显示全部1 000 000位而不断滚动(可在http://ituring.cn/book/2784 下载相关的资源):

pi_string.py

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

输出表明,创建的字符串确实包含精确到小数点后1 000 000位的圆周率值:

3.14159265358979323846264338327950288419716939937510...
1000002

对于可处理的数据量,Python没有任何限制,只要系统的内存足够多。

10.1.7 圆周率值中包含你的生日吗

下面来扩展刚才的程序,以确定某个人的生日是否包含在圆周率值的前1 000 000位中:

>>> --snip--(前面的代码不变)
>>> for line in lines:
>>> pi_string += line.strip()
>>> birthday = input("Enter your birthday, in the form mmddyy: ")  #用户输入生日
>>> if birthday in pi_string:  #检查这个字符串是否包含在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.")

运行程序:
Enter your birthdate, in the form mmddyy: 120372
Your birthday appears in the first million digits of pi!

10.2 写入文件

保存数据的最简单的方式之一是将其写入文件中。

10.2.1 写入空文件

要将文本写入文件,在调用open() 时需提供另一个实参,告诉Python你要写入打开的文件。我们将一条简单的消息存储到文件中:

write_message.py

>>> filename = 'programming.txt'
>>> with open(filename, 'w') as file_object:
>>>         file_object.write("I love programming.")

调用open() 时有两个实参,第一个实参是要打开的文件的名称,第二个实参('w' )以写入模式打开这个文件。打开文件时,可指定读取模式 ('r')、写入模式 ('w' )、附加模式 ('a' )或读写模式 ('r+'),若未指定,Python将以默认的只读模式打开文件。

如果要写入的文件不存在,函数open() 将自动创建它。然而,以写入模式('w' )打开文件时千万要小心,因为如果指定的文件已经存在,Python将在返回文件对象前清空该文件的内容。

上面程序没有终端输出,但如果打开文件programming.txt,将看到其中包含如下一行内容:

programming.txt
I love programming.

注意 Python只能将字符串写入文本文件。要将数值数据存储到文本文件中,必须先使用函数str() 将其转换为字符串格式。

10.2.2 写入多行

函数write() 不会在写入的文本末尾添加换行符:

>>> filename = 'programming.txt'
>>> with open(filename, 'w') as file_object:
>>>         file_object.write("I love programming.")
>>>         file_object.write("I love creating new games.")

打开programming.txt,将发现两行内容挤在一起:

I love programming.I love creating new games.

要让每个字符串都单独占一行,需要在方法调用write() 中包含换行符:

>>> with open(filename, 'w') as file_object:
>>>         file_object.write("I love programming.\n")
>>>         file_object.write("I love creating new games.\n")

现在,输出:
I love programming.
I love creating new games.

像显示到终端的输出一样,还可以使用空格、制表符和空行来设置这些输出的格式。

10.2.3 附加到文件

如果要给文件添加内容,而不是覆盖原有的内容,考虑附加模式。以附加模式打开文件时,Python不会在返回文件对象前清空文件的内容,而是将写入文件的行添加到文件末尾。如果指定的文件不存在,Python将为你创建一个空文件。

下面修改write_message.py,在既有文件programming.txt中再添加一些你酷爱编程的原因:

write_message.py

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

说明:记录学习笔记,如果错误欢迎指正!写文章不易,转载请联系我。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值