前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >文件和文件异常

文件和文件异常

作者头像
清菡
发布2020-12-02 17:12:46
5.2K0
发布2020-12-02 17:12:46
举报

文章总览图

一,从文件中读取数据

每当需要分析或修改存储在文件中的信息时,读取文件都很有用,对数据分析应用程序来说也非常重要。

读取一个文本文件的内容,重新设置这些数据的格式并将其写入文件,让浏览器能够显示这些内容。

要使用文件文件中的信息,首先需要将信息读取到内存中。可以一次性读取文件的全部内容,也可以每次一行的方式逐步读取。

1.读取整个文件

先创建一个包含几行文本的文件。将文件保存至该程序所在目录中。

输出:

函数open()接受一个参数:要打开的文件的名称。Python在当前执行的文件所在的目录中查找指定的文件。在这个示例中,当前运行的是file_reader.py所在的目录中查找pi_digits.txt。函数open()返回一个表示文件的对象。在这里,open('pi_digits.txt')返回一个表示文件pi_digits.txt的对象。Python将这个对象存储在我们将在后面使用的变量中。

关键字with在不再需要访问文件后将其关闭。这个程序中,调用了open(),但没有调用close()。也可以调用open()和close()来打开和关闭文件,这样做,如果程序存在bug,导致close()语句未执行,文件将不会关闭。未妥善关闭文件可能会导致数据丢失或受损。如果在程序中过早地调用close(),会发现需要使用文件时它已关闭,这会导致更多的错误。

并非在任何情况下都能轻松确定关闭文件的恰当时机,但通过使用前面所示的结构,可让Python去确定:只管打开文件,并在需要时使用它,Python自会在合适的时候将其自动关闭。

使用方法read()读取这个文件的全部内容,并将其作为一个长长的字符串存储在变量contents中。通过打印contents的值,就可将这个文本文件的全部内容显示出来。

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

输出:

2.文件路径

将类似pi_digits.txt这样的简单文件名传递给函数open()时,Python将在当前执行的文件(即.py程序文件)所在的目录中查找文件。

根据组织文件的方式,有时可能要打开不在程序文件所属目录中的文件。要让Python打开不与程序文件位于同一个目录中的文件,需要提供文件路径,它让Python到系统的特定位置去查找。

相对路径:

由于文件夹text_files位于文件夹python_work中,因此可使相对文件路径来打开该文件夹中的文件。相对文件路径让Python到指定的位置去查找,而该位置是相对于当前运行的程序所在目录的。

Python到文件夹python_work下的文件夹text_files中去查找指定的.txt文件。

Windows里是\但在字符串里需要转义,所以得写成\\。(字符串就是在例子中用单引号引起来的内容)。‘

输出:

将文件在计算机中的准确位置告诉Python,这样就不用关心当前运行的程序存储在什么地方了。这称为绝对文件路径。相对路径行不通时,可使用绝对路径。

绝对路径:

绝对路径通常比相对路径更长,因此将其存储在一个变量中,再将该变量传递给open()会有所帮助。

输出:

通过使用绝对路径,可读取系统任何地方的文件。Windows系统有时能够正确地解读文件路径中的斜杠。由于反斜杠在Python中被视为转义标记,为在Windows中确保万无一失,应以原始字符串的方式指定路径,即在开头的单引号前加上r。

输出:

3.逐行读取

读取文件时,常常需要检查其中的每一行:可能要在文件中查找特定的信息,或者要以某种方式修改文件中的文本。

要以每次一行的方式检查文件,可对文件对象使用for循环。

将要读取的文件的名称存储在变量filename中。由于变量filename表示的并非实际文件,它只是一个让Python知道到哪里去查找文件的字符串。可将'pi_digits.txt'替换为要使用的另一个文件的名称。调用open()后,将一个表示文件及其内容的对象存储到了变量file_object中。这里也使用了关键字with,让Python负责妥善地打开和关闭文件。为查看文件的内容,我们通过对文件对象执行循环来遍历文件中的每一行。

输出:

打印每一行时发现空白行更多了。因为在这个文件中,每行的末尾都有一个看不见的换行符,而print语句也会加上一个换行符,因此每行末尾都有两个换行符:一个来自文件,另一个来自print语句。要消除这些多余的空白行,可在print语句中使用rstrip()。

输出:

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

使用关键字with时,open()返回的文件对象只在with代码块内可用。如果要在with代码块外访问文件的内容,可在with代码块内将文件的各行存储在一个列表中,并在with代码块外使用该列表:可以立即处理文件的各个部分,也可推迟到程序后面再处理。

输出:

方法readlines()从文件中读取每一行,并将其存储在一个列表中。接下来,该列表被存储到变量lines中。在with代码块外,我们依然可以使用这个变量。我们使用一个简单的for循环来打印lines中的各行。由于列表lines的每个元素都对应于文件中的一行,因此输出与文件内容一致。

5.使用文件中的内容

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

首先打开文件,并将其中的所有行都存储在一个列表中。创建一个变量pi_string,用于存储圆周率的值。使用一个循环将各行都加入pi_string,并删除每行末尾的换行符。打印这个字符串以及长度。

输出:

在变量pi_string存储的字符串中,包含原来位于每行左边的空格,为删除这些空格,可使用strip()而不是rstrip()。

输出:

获得一个这样的字符串:它包含精确到30位小数的圆周率值。这个字符串长32字符,因为它还包含整数部分的3和小数点。

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

6.包含一百万位的大型文件

有一个文本文件,其中包含精确到小数点后100万位而不是30位的圆周率值,也可创建一个包含所有这些数字的字符串。无需对程序做任何修改,只需将这个文件传递给它即可。只打印小数点后50位,以免终端为显示100万位不断翻滚。

输出:

7.圆周率值中包含自己的生日

输出:

二,写入文件

保存数据的最简单的方式之一是将其写入到文件中。通过将输出写入文件,即便关闭包含程序输出的终端窗口,这些输出也依然存在:可以在程序结束运行后查看这些输出,可与别人分享输出文件,还可编写程序来将这些输出读取到内存中并进行处理。

1.写入空文件

要将文本写入文件,在调用open()时需要提供另一个实参,告诉Python要写入打开的文件。

空文件:

代码:

调用open()时提供了两个实参。第一个实参也是要打开文件的名称。第二个实参('w')告诉Python,我们要以写入模式打开这个文件。打开文件时,可指定读取模式('r'),写入模式('w'),附加模式('a')或让你能够读取和写入文件的模式('r+')。如果省略了模式实参,Python将以默认的只读模式打开文件。

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

使用文件对象的方法write()将一个字符串写入文件。这个程序没有终端输出,如果打开文件programming.txt,看到其中包含如下内容:

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

输出:

2.写入多行

函数write()不会在写入的文本末尾添加换行符,如果写入多行时没有指定换行符:

输出:

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

输出:

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

3.附件到文件

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

输出:

打开文件时指定了实参'a',以便将内容附加到文件末尾,而不是覆盖文件原来的内容。又写入了两行,它们被添加到文件programming.txt末尾。

三,异常

Python使用被称为异常的特殊对象来管理程序执行期间发生的错误。每当发生让Python不知所措的错误时,它都会创建一个异常对象。如果编写了处理该异常的代码,程序将继续运行。如果未对异常进行处理,程序将停止,并显示一个traceback,其中包含有关异常的报告。

异常是使用try-except代码块处理的。try-except代码块让Python执行指定的操作,同时告诉Python发生异常时怎么办。使用了try-except代码块时,即便出现异常,程序也将继续运行:显示你编写的友好的错误消息,而不是令用户迷惑的traceback。

1.处理ZeroDivisionError异常

输出:

traceback中,指出的错误ZeroDivisionError是一个异常对象。Python无法按你的要求做时,就会创建这种对象。在这种情况下,Python将停止运行程序,并指出引发了哪种异常,而我们可根据这些信息对程序进行修改。

2.使用try-except代码块

觉得可能发生了错误时,可编写一个try-except代码块来处理可能引发的异常。

将导致错误的代码行print(5/0)放在了一个try代码块中。如果try代码块中的代码运行起来没有问题,Python将跳过except代码块。如果try代码块中的代码导致了错误,Python将查找这样的except代码块,并运行其中的代码,即其中指定的错误与引发的错误相同。

try代码块中的代码引发了ZeroDivisionError异常,因此Python指出了该如何解决问题的except代码块,并运行其中的代码。这样,用户看到的是一条友好的错误消息,而不是traceback。

输出:

如果try-except代码块后面还有其它代码,程序将接着运行,因为已经告诉了Python如何处理这种错误。

3.使用异常避免崩溃

发生错误时,如果程序还有工作没有完成,妥善处理错误就很重要。这种情况经常会出现在要求用户提供输入的程序中,如果程序能够妥善处理无效输入,就能再提示用户提供有效输入,而不至于崩溃。

输出:

这个程序提示用户输入一个数字,并将其存储到变量first_number中。如果用户输入的不是表示退出的q,就再提示用户输入一个数字,并将其存储到变量second_number中。接下来,计算两个数字的商。这个程序未采取任何处理错误的措施,因此让它执行除数为0的除法运算时,它将崩溃。

不可让用户看到崩溃,用户体验不好。如果用户怀有恶意,会通过traceback获悉程序文件名称,将看到部分不能正确运行的代码。根据这些信息对你的代码进行攻击。

4.else代码块

通过将可能的引发错误的代码放在try-except代码块中,可提高这个程序抵御错误的能力。

输出:

except代码块告诉Python,出现ZeroDivisonError异常时怎么办。如果try代码块因除0错误而失败,就打印1条友好消息,告诉用户如何避免这种错误,程序继续运行。

try-except-else代码块的工作原理:

Python尝试执行代码块中的代码,只要可能引起异常的代码才需要放在try语句中。有一些仅在try代码块成功执行时才需要运行的代码。这些代码应放在else代码块中。except代码块告诉Python,如果它尝试运行try代码块中的代码时引发了指定的异常,该如何处理。

6.分析文本

方法split(),根据一个字符串创建一个单词列表。

方法split()以空格为分隔符将字符串分拆成多个部分,并将这些部分都存储到一个列表中。结果是一个包含字符串中所有单词的列表,虽然有些单词可能包含标点。

输出:

7.使用多个文件

输出:

8.失败时一声不吭

Python中有个pass语句,在代码块中使用它来让Python什么都不做。出现FilNotFoundError异常时,将执行except代码块中的代码,但什么都不会发生。这种错误发生时,不会出现traceback,也没有任何输出。没有迹象表明有文件没找到。

pass语句充当占符位,用户看不到这个文件,但可以读取这个文件,进而处理所有找不到文件的问题。

输出:

四,存储数据

程序都把用户提供的信息存储在列表和字典等数据结构中。用户关闭程序时,总是要保存它们提供的信息。使用json来存储数据。

模块json将简单的Python数据结构转储到文件中,并在程序再次运行时加载该文件中的数据。可以使用json在Python程序之间分享数据。json格式不是Python专用的,可将以json格式存储的数据与使用其它编程语言的人分享。

1.使用json.dump()和json.load()

函数json.dump()接受两个实参:要存储的数据以及可用于存储数据的文件对象。

使用函数json.dump()将数字列表存储到文件numbers.json中。

输出:

使用函数json.load()加载存储在numbers.json中的信息,并将其存储到变量numbers中。

输出:

这是种在程序间共享数据的方式。

2.保存和读取用户生成的数据

调用json.dump(),并将用户和一个文件对象传递给它,从而将用户名存储到文件中。

输出:

使用json.load()中的信息读取到变量username中。恢复用户名后,就可以欢迎用户回来了。

输出:

3.重构

代码能正确地运行,但可以做进一步的改进。将代码划分为一系列完成具体工作的函数。这样的过程被称为重构。

输出:

函数greet_user()所做的不仅仅是问候用户,还在存储了用户名时获取它,而在没有存储用户名时提示用户输入一个。

调用get_stored_username(),这个函数只负责获取存储的用户名(如果已存储)。调用get_new_username(),这个函数只负责获取并存储新用户的用户名。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-01-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 清菡软件测试 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档