作者|弗拉德来源|存储的数据量很大,每当需要分析或修改存储在文件中的信息时,读取??文件就很有用,特别是对于数据分析应用。例如,您可以编写一个程序来读取文本文件的内容、重新格式化数据并将其写入文件以便浏览器可以显示内容。要使用文本文件中的信息,首先需要将其读入内存。您可以通过一次读取文件的全部内容或一次读取一行来完成此操作。读取整个文件要读取文件,需要一个包含几行文本的文件。我们先创建一个文件,其中包含精确到小数点后30位的pi值,并在小数点后每10位换行:3.141592653589793238462643383279我们将其保存为pi_digits.txt文件withopen('pi_digits.txt')作为文件对象:内容=文件对象。read()print(contents)我们先来看一下函数open()。要以任何方式使用文件——即使只是打印其内容——您必须首先打开文件以便访问它。函数open()接受一个参数:要打开的文件的名称。Python在与当前正在执行的文件相同的目录中查找指定的文件。在这个例子中,假设我们将文件保存为file_reader.py,那么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会在需要时自动关闭它。时机成熟。把它关掉。通过打印contents的值,可以显示这个文本文件的全部内容:3.141592653589793238462643383279文件路径当你传递一个像pi_digits这样的简单文件名时。在文件所在的目录中找到该文件。根据您组织文件的方式,有时您可能希望打开与您的程序文件不在同一目录中的文件。例如,你可能将程序文件存放在python_work文件夹中,在python_work文件夹中,有一个名为text_files的文件夹,用于存放程序文件操作的文本文件。虽然文件夹text_files包含在文件夹python_work中,但是仅仅将位于该文件夹中的文件名传递给open()是不可行的,因为Python在搜索时只查找文件夹python_work,而不是其子文件夹text_files。要让Python打开一个与程序文件不在同一目录中的文件,您需要提供一个文件路径,告诉Python在系统的特定位置查找。由于文件夹text_files位于文件夹python_work中,您可以使用相对文件路径打开该文件夹中的文件。相对文件路径告诉Python在指定位置查找,该位置相对于当前运行程序所在的目录。在Linux和OSX中,可以这样写代码:withopen('text_files/filename.txt')asfile_object:这行代码告诉Python在python_work文件夹下的text_files文件夹中找到指定的.txt文件。在Windows上,在文件路径中使用反斜杠\而不是斜杠/:withopen('text_files\filename.txt')asfile_object:您还可以告诉Python文件在您计算机上的确切位置,这样就不会关心当前运行程序的存储位置。这称为绝对文件路径。当相对路径不起作用时,可以使用绝对路径。例如,如果text_files不在文件夹python_work中,而是在文件夹other_files中,则将路径“text_files/filename.txt”传递给open()将不起作用,因为Python仅在文件夹python_work中查找该位置。要准确指定您希望Python查找的位置,您需要提供完整路径。绝对路径通常比相对路径长,因此在将变量传递给open()之前将其存储在变量中会有所帮助。在Linux和OSX上,绝对路径看起来像这样:file_path='/home/ehmatthes/other_files/text_files/filename.txt'withopen(file_path)asfile_object:在Windows上,它们看起来像这样:file_path='C:\Users\ehmatthes\other_files\text_files\filename.txt'withopen(file_path)asfile_object:通过使用绝对路径,您可以读取系统中任何位置的文件。目前,最简单的方法是要么将文本文件存放在程序文件所在目录下,要么存放在程序文件所在目录下的文件夹(如text_files)中。当你逐行阅读一个文件时,你经常需要检查其中的每一行:你可能想在文件中找到特定的信息,或者你可能想以某种方式修改文件中的文本。例如,您可能想要遍历包含天气数据的文件并使用天气描述中包含单词sunny的行。在新闻文章中,您可能会查找包含标记的行并以某种方式对其进行格式化。要一次一行地检查文件,请在文件对象上使用for循环:filename='pi_digits.txt'withopen(filename)asfile_object:forlineinfile_object:print(line)thenameofthefileweare将读取存储在变量文件名中,这是处理文件时的常见做法。由于变量文件名不代表实际文件-它只是一个字符串,告诉Python在哪里可以找到文件,您可以轻松地将'pi_digits.txt'替换为您要使用的另一个文件的名称。调用open()后,表示文件及其内容的对象存储在变量file_object中。此处还使用了with关键字,让Python负责正确打开和关闭文件。为了查看文件的内容,我们通过遍历文件对象来遍历文件中的每一行。当我们打印每一行的时候,发现空行比较多:3.141592653589793238462643383279为什么会出现这些空行呢?因为在这个文件中,每行末尾都有一个看不见的换行符,而打印语句也加了一个换行符,所以每行末尾有两个换行符:一个来自文件,一个来自打印语句。创建包含文件每一行内容的列表当使用关键字with时,open()返回的文件对象仅在with块内可用。如果要访问with块之外的文件内容,请将文件的行存储在with块内的列表中,并在with块外使用该列表:您可以立即处理文件的某些部分或推迟到后面的程序。以下示例将文件pi_digits.txt的行存储在with块内的列表中,并在with块外打印它们:filename='pi_digits.txt'withopen(filename)asfile_object:lines=file_object.readlines()forlineinlines:print(line.rstrip())我们首先使用readlines()方法从文件中读取每一行并将其存储在列表中接下来,该列表存储在变量lines中;在with块之外,我们仍然可以使用这个变量。我们使用一个简单的for循环来逐行打印各个行。由于列表lines的每个元素对应于文件中的一行,因此输出与文件内容完全相同。一旦使用其内容将文件读入内存,就可以以任何方式使用数据。pi的值在下面以简单的方式使用。首先,我们将创建一个字符串,其中包含存储在文件中的所有数字,没有任何空格:filename='pi_digits.txt'withopen(filename)asfile_object:lines=file_object.readlines()pi_string=''forlineinlines:pi_string+=line.rstrip()print(pi_string)print(len(pi_string))和前面的例子一样,我们先打开文件,把里面所有的行存入一个列表。我们创建了一个变量-pi_string来存储pi的值。接下来,我们使用循环将行连接到pi_string并删除每行末尾的换行符。接下来,我们打印这个字符串及其长度:3.14159265358979323846264338327936在变量pi_string中存储的字符串中,它包含每行左侧的空格。要删除这些空格,请使用strip()而不是rstrip():filename='pi_30_digits.txt'withopen(filename)asfile_object:lines=file_object.readlines()pi_string=''forlineinlines:pi_string+=line.strip()print(pi_string)print(len(pi_string))这样,我们得到了这样一个字符串:它包含了精确到小数点后30位的pi值。这个字符串有32个字符长,因为它还包含3个整数部分和一个小数点:3.14159265358979323846264338327936写入文件保存数据的最简单方法之一是将其写入文件。通过将输出写入文件,即使包含程序输出的终端窗口关闭,输出仍然存在:您可以在程序运行结束后查看输出,可以与其他人共享输出文件,还可以将程序编写到将输出读入内存并进行处理。写入空文件要将文本写入文件,您需要在调用open()时提供另一个参数,告诉Python您要写入打开的文件。为了了解这是如何工作的,让我们将一条简单的消息存储到一个文件中,而不是将其打印到屏幕上:filename='programming.txt'withopen(filename,'w')asfile_object:file_object.write("Iloveprogramming.")在此示例中,调用open()时提供了两个参数。第一个参数也是要打开的文件的名称;第二个参数w告诉Python我们想以写模式打开这个文件。打开文件时,您可以指定读取模式r、写入模式w、追加模式a或模式r+,使您能够读取和写入文件。如果省略模式参数,Python将默认以只读模式打开文件。如果您要写入的文件不存在,函数open()将自动创建它。但是,使用w打开文件写入时要小心,因为如果指定的文件已经存在,Python会在返回文件对象之前清空文件。我们使用文件对象的write()方法将字符串写入文件。该程序没有终端输出,但如果您打开文件programming.txt,您会看到它包含以下行:我喜欢编程。与您计算机上的其他文件相比,此文件没有什么不同。您可以打开它,向其中输入新文本,复制其内容,向其中粘贴内容等。写入多行write()函数不会在您写入的文本末尾添加换行符,因此如果您写入多行而不指定换行符,文件可能看起来不像您期望的那样:filename='programming.txt'withopen(filename,'w')asfile_object:file_object.write("Iloveprogramming.")file_object.write("Ilovecreatingnewgames.")如果你打开programming.txt,你会发现两行挤在一起:我喜欢编程。我喜欢创造新游戏。要让每个字符串独占一行,请在write()语句中包含一个换行符:filename='programming.txt'withopen(filename,'w')asfile_object:file_object.write("Iloveprogramming.\n")file_object.write("Ilovecreatingnewgames\n")现在,输出出现在不同的行中:我喜欢编程。我喜欢创造新游戏。追加到文件如果要向文件添加内容而不是覆盖原始内容,可以以追加模式打开文件。当你以附加模式打开文件时,Python在返回文件对象之前不会清空文件,你写入文件的行将被附加到文件末尾。如果指定的文件不存在,Python会为你创建一个空文件。filename='programming.txt'withopen(filename,'a')asfile_object:file_object.write("我也喜欢在大型数据集中寻找意义。\n")file_object.write("我喜欢创建可以在abrowser.\n")我们在打开文件的时候指定了实参a,这样内容就会追加到文件的末尾,而不是覆盖文件原来的内容。然后,我们又写了两行,添加到文件programming.txt的末尾:我喜欢编程。我喜欢创造新游戏。我也喜欢在大型数据集中寻找意义。我喜欢创建可以在浏览器中运行的应用程序。最后的结果是文件原来的内容还在,后面跟着我们刚刚添加的内容。19作业17-1在文本编辑器中创建一个新文件,写几句话来总结到目前为止你对Python的了解。将该文件命名为learning_python.txt,并将其存放在与您编写的用于完成本章练习的程序相同的目录中。编写一个程序来读取整个文件并打印出来。17-2Guest:编写一个程序,提示用户输入他们的名字;用户响应后,将他们的名字写入文件guest.txt。如果要查看作业答案,可以到我的Githu仓库17-1_17-2文件夹下