作者 | 弗拉德
起源 | 弗拉德(公众号: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
8979323846
2643383279
为何会呈现这些空白行呢? 因为在这个文件中,每行的开端都有一个看不见的换行符,而 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 2643383279
36
在变量 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.141592653589793238462643383279
36
写入文件
保留数据的最简略的形式之一是将其写入到文件中。通过将输入写入文件,即使敞开蕴含程 序输入的终端窗口,这些输入也仍然存在: 你能够在程序完结运行后查看这些输入,可与他人分享输入文件,还可编写程序来将这些输入读取到内存中并进行解决。
写入空文件
要将文本写入文件,你在调用 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 下