作者 | 弗拉德
起源 | 弗拉德(公众号:fulade_me)

从文件中读取数据

文本文件可存储的数据量很多,每当须要剖析或批改存储在文件中的信息时,读取文件都很有用,对数据分析应用程序来说尤其 如此。例如,你能够编写一个这样的程序:读取一个文本文件的内容,从新设置这些数据的格局 并将其写入文件,让浏览器可能显示这些内容。
要应用文本文件中的信息,首先须要将信息读取到内存中。为此,你能够一次性读取文件的全部内容,也能够以每次一行的形式逐渐读取。

读取整个文件

要读取文件,须要一个蕴含几行文本的文件。上面首先来创立一个文件,它蕴含准确到小数点后30位的圆周率值,且在小数点后每10位处都换行:

3.1415926535 8979323846 2643383279

咱们把它保留为pi_digits.txt文件

with open('pi_digits.txt') as file_object:     contents = file_object.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.1415926535 8979323846 2643383279

文件门路

当你将相似pi_digits.txt这样的简略文件名传递给函数open()时,Python将在以后执行的文件所在的目录中查找文件。
依据你组织文件的形式,有时可能要关上不在程序文件所属目录中的文件。例如,你可能将 程序文件存储在了文件夹python_work中,而在文件夹python_work中,有一个名为text_files的文件夹,用于存储程序文件操作的文本文件。尽管文件夹text_files蕴含在文件夹python_work中,但仅向open()传递位于该文件夹中的文件的名称也不可行,因为Python只在文件夹python_work中查找,而不会在其子文件夹text_files中查找。要让Python关上不与程序文件位于同一个目录中的文件,须要提供文件门路,它让Python到零碎的特定地位去查找。
因为文件夹text_files位于文件夹python_work中,因而可应用绝对文件门路来关上该文件夹中的文件。绝对文件门路让Python到指定的地位去查找,而该地位是绝对于以后运行的程序所在目录的。在Linux和OS X中,你能够这样编写代码:

with open('text_files/filename.txt') as file_object:

这行代码让Python到文件夹python_work下的文件夹text_files中去查找指定的.txt文件。在Windows零碎中,在文件门路中应用反斜杠\而不是斜杠/:

with open('text_files\filename.txt') as file_object:

你还能够将文件在计算机中的精确地位通知Python,这样就不必关怀以后运行的程序存储在什么中央了。这称为相对文件门路。在相对路径行不通时,可应用绝对路径。例如,如果text_files并不在文件夹python_work中,而在文件夹other_files中,则向open()传递门路'text_files/ filename.txt'行不通,因为Python只在文件夹python_work中查找该地位。为明确地指出你心愿Python到哪里去查找,你须要提供残缺的门路。
绝对路径通常比相对路径更长,因而将其存储在一个变量中,再将该变量传递给open()会有所帮忙。在Linux和OS X中,绝对路径相似于上面这样:

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

而在Windows零碎中,它们相似于上面这样:

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

通过应用绝对路径,可读取零碎任何中央的文件。就目前而言,最简略的做法是,要么将 据文件存储在程序文件所在的目录,要么将其存储在程序文件所在目录下的一个文件夹(如text_files)中。

逐行读取

读取文件时,经常须要查看其中的每一行:你可能要在文件中查找特定的信息,或者要以某种形式批改文件中的文本。例如,你可能要遍历一个蕴含天气数据的文件,并应用天气形容中蕴含字样sunny的行。在新闻报道中,你可能会查找蕴含标签<headline>的行,并按特定的格局设置它。
要以每次一行的形式查看文件,可对文件对象应用for循环:

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

咱们将要读取的文件的名称存储在变量filename中,这是应用文件时一种常见的做法。因为变量filename示意的并非理论文件——它只是一个让Python晓得到哪里去查找文件的字符串,因而可轻松地将'pi_digits.txt'替换为你要应用的另一个文件的名称。

调用open()后,将一个示意文件及其内容的对象存储到了变量file_object中。这里也应用了关键字with,让Python负责妥善地关上和敞开文件。为查看文件的内容,咱们通过对文件对象执行循环来遍历文件中的每一行,咱们打印每一行时,发现空白行更多了:

3.1415926535 89793238462643383279

为何会呈现这些空白行呢?因为在这个文件中,每行的开端都有一个看不见的换行符,而print语句也会加上一个换行符,因而每行开端都有两个换行符:一个来自文件,另一个来自print语句。

创立一个蕴含文件各行内容的列表

应用关键字with时,open()返回的文件对象只在with代码块内可用。如果要在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代码块外,咱们仍然能够应用这个变量。咱们应用一个简略的for循环来打印lines中的各行。因为列表lines的每个元素都对应于文件中的一行,因而输入 与文件内容完全一致。

应用文件的内容

将文件读取到内存中后,就能够以任何形式应用这些数据了。上面以简略的形式应用圆周率 的值。首先,咱们将创立一个字符串,它蕴含文件中存储的所有数字,且没有任何空格:

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

就像前一个示例一样,咱们首先关上文件,并将其中的所有行都存储在一个列表中。咱们创立了一个变量——pi_string,用于存储圆周率的值。接下来,咱们应用一个循环将各行都退出pi_string,并删除每行开端的换行符。接着,咱们打印这个字符串及其长度:

3.1415926535 8979323846 264338327936

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

filename = 'pi_30_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) print(len(pi_string))

这样,咱们就取得了一个这样的字符串:它蕴含准确到30位小数的圆周率值。这个字符串长32字符,因为它还蕴含整数局部的3和小数点:

3.14159265358979323846264338327936

写入文件

保留数据的最简略的形式之一是将其写入到文件中。通过将输入写入文件,即使敞开蕴含程 序输入的终端窗口,这些输入也仍然存在:你能够在程序完结运行后查看这些输入,可与他人分享输入文件,还可编写程序来将这些输入读取到内存中并进行解决。

写入空文件

要将文本写入文件,你在调用open()时须要提供另一个实参,通知Python你要写入关上的文 件。为明确其中的工作原理,咱们来将一条简略的音讯存储到文件中,而不是将其打印到屏幕上:

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将在返回文件对象前清空该文件。
咱们应用文件对象的办法write()将一个字符串写入文件。这个程序没有终端输入,但如果你关上文件programming.txt,将看到其中蕴含如下一行内容:

I love programming.

相比于你的计算机中的其余文件,这个文件没有什么不同。你能够关上它、在其中输出新文本、复制其内容、将内容粘贴到其中等。

写入多行

函数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()语句中蕴含换行符:

filename = 'programming.txt'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.

追加写入文件

如果你要给文件增加内容,而不是笼罩原有的内容,能够附加模式关上文件。你以附加模式关上文件时,Python不会在返回文件对象前清空文件,而你写入到文件的行都将增加到文件开端。如果指定的文件不存在,Python将为你创立一个空文件。

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

咱们关上文件时指定了实参a,以便将内容附加到文件开端,而不是覆盖文件原来的内容。而后,咱们又写入了两行,它们被增加到文件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.

最终的后果是,文件原来的内容还在,它们前面是咱们刚增加的内容。 19

小作业
17-1 在文本编辑器中新建一个文件,写几句话来总结一下你至
此学到的Python常识。将这个文件命名为 learning_python.txt,并将其存储到为实现本章练习而编写的程序所在的目录中。编写一个程序,读取整个文件,并打印。
17-2 访客:编写一个程序,提醒用户输出其名字;用户作出响应后,将其名字写入到文件 guest.txt中。

想查看作业答案能够去我的Githu仓库在文件夹17-1_17-2