python基础篇(二十一)——文件和异常(上)

Posted 一计之长

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python基础篇(二十一)——文件和异常(上)相关的知识,希望对你有一定的参考价值。

前言

  我们前面文章给大家介绍了Python中的相关知识;本文开始给大家介绍Python中的文件和在写程序中遇到的一些异常。首先给大家介绍从文中读取数据;

一、从文件中读取数据

  文本文件可存储的数据量多的难以置信;天气数据、交通数据、社会经济数据、文学作品等。每当需要分析或修改存储在文件中的信息时,读取文件都很有用,对数据分析应用程序来说尤其如此。例如,你可以编写一个这样程序;读取一个文本文件内容,重新设置这些数据的格式并将其写入文件,让浏览器能够显示这些内容。
  要使用文本中的信息,首先需要将信息读取的内存中。为此,你可以一次性读取文件的全部内容,也可以以每次一行的方式逐步读取。

1、读取整个文件

  要读取文件,需要一个包含几行文本的文件的内容。下面首先来创建一个文件,它包含精确到小数点后30位的圆周率,且小数点后每10位都换行:具体文件如下:

  要动手尝试后续示例,可在编辑器中输入这些数据行,再将文件保存为demo.txt。然后,将该文件保存到如图所示的目录中(一定要与程序在同一目录中)。下面的程序打开并读取文件,再将其内容显示到屏幕上;

with open(\'demo.txt\') as file_object:
    contents = file_object.read()
    print(contents)

  在这个程序中,第1行代码做了大量的工作,我们先来看看函数open()。要以任何方式使用文件——哪怕仅仅是打印其内容,都得先打开文件,这样才能访问它。函数open()接受一个参数:要打开文件的名称。Python在当前执行的文件所在目录中查找指定文件。在这个示例中,当前运行的是test2.py,因此Python在test.py所在目录中查找demo.txt。函数open()返回一个表示文件的对象。在这里,open(\'demo.txt\')返回一个表示文件demo.txt的对象;Python将这个对象存储在我们这在后面使用的变量中。
  关键字with在不再需要访问文件后将其关闭。在这个程序中,注意到我们调用了open(),但没有调用close();你也可以调用open()close()来打开和关闭文件,但这样做时,如果程序存在bug,导致close()语句未执行,文件将不会关闭。这看似微不足道,但未妥善地关闭文件可能会导致数据丢失或受损。如果在程序中过早地调用close(),你会发现需要使用文件时它已关闭(无法访问),这会导致更多的错误。并非在任何情况下都轻松确定关闭文件恰当时机,但通过使用前面所示的结构,可以让Python去确定;你只管打开文件,并在需要时使用它,Python自会在合适的时候自动将其关闭。
  有了表示demo.txt的文件对象后,我们使用方法read()(前述程序的第2行)读取文件的全部内容,并将其作为一个长长的字符串存储在变量contents中。这样,通过打印contents的值,就可将这个文本文件的全部内容显示出来:

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

with open(\'demo.txt\') as file_object:
    contents = file_object.read()
    print(contents.rstrip())

  本文在前面提到过,Python方法rstrip()删除(剥除)字符串末尾的空白。现在,输出与原始文件的内容完全相同,具体实现结果如下:

2、文件路径

  当你将类似demo.txt这样的简单文件名传递给函数open()时,Python将在当前执行的文件(即.py程序文件)所在的目录中查找文件。
  根据我们组织文件的方式,有时可能要打开不在程序文件所属目录中的文件。例如,我们将程序文件存储在了文件夹test中,而在文件test中,有一个名为text_file的文件夹,用于存储程序文件操作的文本文件。虽然文件夹test_file包含在文件夹test中,但仅向open()传递位于该文件夹中文件的名称也不可行,因为Python只在文件夹test中查找,而不会在其子文件夹test_file中查找。要让Python打开不与程序文件位于相同一个目录中的文件,需要提供文件路径,它让Python到系统的特定位置去查找。
  由于文件夹test_file文件文件夹test中,因此, 可使用相对文件路径来打开该文件夹中的文件。相对文件路径让Python到指定的位置去查找,而该位置是相对于当前运行的程序所在目录的。在Linux和OS X中,我门可以这样编写代码:

with open(\'text_file/filename.txt\') as file_objects:

  这行代码让Python到文件夹test下的文件夹tset_file中去查找指定的.txt文件。在windows系统中,在文件路径中使用\\而不是/

with open(\'text_file\\filename.txt\') as file_objects:

  我们还可以将文件在计算中的准确位置告诉Python,这样就不用关心当前运行的程序存储在什么地方了。这称为绝对路径。在相对路径行不通时,可使用绝对路径。例如,如果test_file并不在文件夹test中,而在文件夹other_files中,则向open()传递路径text_file/filename.txt是不行的,因为Python只在文件夹test中查找该位置。为明确地指出我们希望Python到哪里去查找,我们需要提供完整的路径。
  绝对路径通常比相对路径更长,因此将其存储在一变量中,再将该变量传递给open()会有所帮助。在Linux和OS X中,绝对路径类似于下面这样:

file_path = \'/home/ehmatthes/other_files/text_files/filename.txt\'
with open(file_open) as file_object:

  而在window系统中,他们类似于,它类似于下面这样:

file_path = \'C:\\Users\\ehmatthes\\other_files\\text_files\\filename.txt\'
with open(file_open) as file_object:

  通过使用绝对路径,可读取系统任何地方的文件。就目前而言,最简单的做法就是:要么将数据文件存储在程序文件所在的目录,要么将其存储在程序文件呢所在目录下的一个文件夹(如text_file)中。
  这里需要我们注意的是:windows系统有时候能够正确地解读文件路径中的斜杠。如果你使用的是windows系统,且结果不符合预期,请确保在文件路径中使的是反斜杠。另外,由于反斜杠是在Python中被视为是转义标记,为在windows中确保万无一失,应以原始字符字符串的方式指定路径,即在开头的单引号前面加上r。

3、逐行读取

  读取文件时,常常需要检查其中的每一行;你可能要在文件中查找特定的信息,或者要以某种方法修改文件中的文本。例如,我们可能要遍历一个包含天气数据的文件,并使用天气描述总包含字样sunny的行。在新闻报道中,你可能会查找包含标签的行,并按特定的格式设置它。
  要以每一次执行的方式检查文件,可对文件对象使用for循环

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

  我们将要读取的文件名称存储在变量filename中,这是使用文件时一种常见的做法。由于变量filename表示的并非实际文件——它只是一个让Python知道哪里去查找文件的字符串,因此可轻松地将demo.txt替换为我们要使用的另一个文件的名称。调用open()后,将让Python负责妥善地打开和关闭文件。为查看文件的内容,我们通过对文件对象执行循环来遍历文件中的每一行。我们打印每一行时,发现空白行更多了,具体如下图所示:

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

filename = \'demo.txt\'
with open(filename) as file_object:
    for line in file_object:
        print(line.rstrip())

  现在,输出又与文件内容完全相同了:

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

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

filename = \'demo.txt\'
with open(filename) as file_object:
    lines = file_object.readlines()
    for line in lines:
        print(line.rstrip())

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

5、使用文件的内容

  将文件读取到内存后,就可以任何方式使用这些数据了。下面以简单的方式使用圆周率的值。首先,我们将创建一个字符串,它包含文件中存储的所有数字,且没有任何空格:

filename = \'demo.txt\'
with open(filename) as file_object:
    lines = file_object.readlines()
    de_string = \'\'
    for line in lines:
        de_string += line.rstrip()
print(de_string)
print(len(de_string))

  就像前面的示例一样,我们首先打开文件,并将其中的所有行都存储在一个列表中。首先,我们创建了一个变量——de_string,用于存储圆周率的值。接下来,我们使用一个循环将各行都加入de_string,并删除每行末尾的换行符,最后骂我们将其字符串的长度打印出来,具体结果如下:

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

filename = \'demo.txt\'
with open(filename) as file_object:
    lines = file_object.readlines()
    de_string = \'\'
    for line in lines:
        de_string += line.strip()
print(de_string)
print(len(de_string))

  这样,我们就获得了一个这样的字符串:它包含精确到30位小数的圆周率值。这个字符串长32字符,因为它还包含整数部分的3和小数点,具体执行结果如下:

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

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

  前面我们分析的都是一个只含有三行的文本文件,但这些代码示例也可以处理大得多的文件。如果我们有一个文本文件,其中包含精确到小数点后10000000位而不是30位的圆周率值,也可以创建一个包含所有这些数字的字符串。为此,我们无需对前面的程序做任何修改,只需将这个文件传递给它即可。在这里,我们只打印到小数点后30位,以免终端为显示全部100000000位而不断地翻滚。

filename = \'demo.txt\'
with open(filename) as file_object:
    lines = file_object.readlines()
    de_string = \'\'
    for line in lines:
        de_string += line.strip()
print(de_string[:22] + "...")
print(len(de_string))

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

  对于我们可处理的数据量,Python没有任何限制;只要系统的内存足够多,我们想处理多少数据都可以。

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

  我一直想知道自己的生日是否包含在圆周率中。下面来扩展刚写好的程序,已确定某个人的生日是否包含在圆周率的前32位中。为此,我们可将生日表示为一个由数字组成的字符串,再检查这个字符串是否包含在de_string中:

filename = \'demo.txt\'
with open(filename) as file_object:
    lines = file_object.readlines()
    de_string = \'\'
    for line in lines:
        de_string += line.strip()
birthday = input("请输入您的生日,请采用标准的日期格式")
if birthday in de_string:
    print("您的生日出现在32位圆周率中")
else:
    print("您的生日不在这32位圆周率中")

  我们首先提示用户输入其生日,接下来我们检查这个字符串是否包含在de_string中。运行以下这个程序即:

  我的生日不在前32位圆周率中!读取文件后,就可以以我们想象的任何方式对其进行分析。

二、写入文件

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

1、写入多行

  函数write()不会再你写入的文件末尾添加换行符,因此如果你写入多行时没有指定换行符,文件看起来可能不是我们所希望的那样:

filename = \'demo1.txt\'
with open(filename, \'w\') as file_object:
    file_object.write("I Love Studing Python!!")
    file_object.write("I Love creating new python programming!!!")

  如果我们打开该文件,将发现两行内容挤在一起,具体如下:

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

filename = \'demo1.txt\'
with open(filename, \'w\') as file_object:
    file_object.write("I Love Studing Python!!\\n")
    file_object.write("I Love creating new python programming!!!\\n")

  现在,输出出现在不同行中:

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

2、写入空文件

  要将文本写入文件,你在调用open()时需要提供另一个实参,告诉Python我们要写入打开的文件。为明白其中的工作原理,我们来将一条简单的消息存储到文件中,而不是将其打印到屏幕上,具体实现如下:

filename = \'demo2.txt\'
with open(filename, \'w\') as file_object:
    file_object.write("I Love Studing Python!!\\n")

  在这个示例中,调用open()时提供了两个实参。第一个实参也是要打开的文件的名称;第二个实参(‘w’)告诉Python,我们要以写入模式打开这个文件。打开文件时,可指定读取模式(‘r’)、写入模式(‘w’)、附加模式(‘a’)或让你能够读取和写入文件的模式(‘r+’)。如果你省略了模式实参,Python将以默认的只读模式打开文件。
  如果你要写入的文件不存在,函open()将自动创建它。然而,以写入(‘w’)模式打开文件时,千万要小心,因为如果指定的文件已经存在,Python将在返回文件对象前清空该文件。
  我们使用文件对象方法write()将一个字符串写入文件。这个程序没有终端输出,但如果我们打开文件,将其看到其中包含如下一行内容:

  相比于我们的计算机中的其他文件,这个文件没有什么不同。我们可以打开它、在其中输入新文本、复制内容、将内容粘贴到其中等。
  这里需要我们注意的是:Python只能将字符串写入文本文件。要将数值数据存储到文本文件中,必须先使用函数str()将其转换为字符串格式。

3、附加到文件

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

filename = \'demo1.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 browers.\\n")

  我们首先打开文件时,指定了实参a,以便将内容附加到文件末尾,而不是覆盖文件原来的内容,另外,我们又写入了两行,它们添加到文件末尾,具体执行结果如下:

  最终的结果是:文件原来的内容还在,它们后面是我们刚添加的内容。

总结

  我们前面文章给大家介绍了Python中的相关知识;本文开始给大家介绍Python中的文件和在写程序中遇到的一些异常。本文主要给大家介绍了文件的写入和读取。Python是一门注重实际操作的语言,它是众多编程语言中最简单,也是最好入门的。当你把这门语言学会了,再去学习java、go以及C语言就比较简单了。当然,Python也是一门热门语言,对于人工智能的实现有着很大的帮助,因此,值得大家花时间去学习。生命不息,奋斗不止,我们每天努力,好好学习,不断提高自己的能力,相信自己一定会学有所获。加油!!!

 

以上是关于python基础篇(二十一)——文件和异常(上)的主要内容,如果未能解决你的问题,请参考以下文章

Python开发第二十一篇:Web框架之Django基础

MySQL从入门到精通高级篇(二十一)数据库优化步骤_查看系统性能参数

MySQL从入门到精通高级篇(二十一)数据库优化步骤_查看系统性能参数

ParisGabriel:Python全栈工程师(0基础到精通)教程 第二十一课(包模块 的导入)

python 全栈 python基础 (二十一)logging日志模块 json序列化 正则表达式(re)

我的第二十一篇博客---Mysql强化及应用于python