在上一篇《手把手陪您学Python》33——文件的关闭中,我们学习了关闭文件的两种方法。
今天,我们将学习文件的写入。如同学习文件的读取,是为了让我们了解Python读取文件的原理一样,本篇的内容也是为了让大家理解Python写入文件的基础原理。
文件写入的方法有write()和writelines()两种,但无论哪种写入方法,都要先用open()打开文件。当然,这次打开文件就不能使用默认的只读模式“r”了,而要从我们上一篇列出的文件模式列表中,选择可以写入文件的模式。
所以,这一篇中还会介绍一下不同打开模式之间的区别。这里再将常用的几种打开模式列举一下,以便大家查阅。
模式 | 描述 |
r | 只读模式 (默认),打开已有文件。 |
r+ | 读写模式,打开已有文件,可读可写且不分先后。 |
w | 只写模式,创建新文件,如果已有同名文件存在则覆盖。 |
x | 只写模式,创建新文件,如果已有同名文件存在则创建失败。 |
w+ | 写读模式,创建新文件,如果已有同名文件存在则覆盖,而且要求先写入再读取。 |
a | 追加模式,如果文件已存在则直接打开,如果不存在则创建,写入时在文件的末尾追加,不能读取。 |
a+ | 追加读取模式,如果文件已存在则直接打开,如果不存在则创建,写入时在文件的末尾追加,同时能够读取。 |
1、写入空白文件
先从最简单的写入空白文件开始,我们可以使用write()方法,文件打开模式可以使用“w”。由于使用该种模式写入时,如果原文件夹中已经有同名文件的话,Python会将原文件覆盖,并返回一个空文件来等待写入,所以大家在命名时要稍微注意一下。
In [1]: path = 'lesson/text/blank.txt' # 将文件写入blank.txt
with open(path, encoding = 'utf-8', mode = 'w') as file_object:
file_object.write('《手把手陪您学Python》1——为什么要学Python?')
写入文件后,并不会在程序里有什么显示,只有按照文件的路径打开我们写入的文件,才能够在文件中看到我们刚才写入的内容。
由于“w”模式会将文件中的同名文件覆盖,如果再写入文件时不确定是否有同名文件,或者想即使有也能够避免原文件被覆盖的话,可以使用“x”模式。在这种模式下,如果要打开的文件名与相同路径中已存在的文件同名时,会创建失败,从而保护同名原文件不会被清空。
由于我们刚刚已经建立了一个blank.txt文件,下面我们就使用“x”模式打开文件,看看会出现什么情况。
In [2]: path = 'lesson/text/blank.txt'
with open(path, encoding = 'utf-8', mode = 'x') as file_object:
file_object.write('《手把手陪您学Python》1——为什么要学Python?')
Out[2]: ---------------------------------------------------------------------------
FileExistsError Traceback (most recent call last)
<ipython-input-11-3057738047f5> in <module>
1 path = 'lesson/text/blank.txt'
----> 2 with open(path, encoding = 'utf-8', mode = 'x') as file_object:
3 file_object.write('《手把手陪您学Python》1——为什么要学Python?')
FileExistsError: [Errno 17] File exists: 'lesson/text/blank.txt'
和我们介绍的一样,错误信息提示文件已经存在,这样就可以避免同名文件被覆盖的情况了。
2、读写模式W+
刚才是通过打开文件的方式看到写入的内容的,如果想直接在程序中看到,可以在写入文件后加上我们上一篇所学的文件读取的方法,就能够将我们刚才写入的内容读取出来了。但是要注意,新加入的读取文件的代码要放在with关键字的下一级缩进处,否则文件就会被提前关闭了。
In [3]: path = 'lesson/text/blank.txt'
with open(path, encoding = 'utf-8', mode = 'w') as file_object:
file_object.write('《手把手陪您学Python》1——为什么要学Python?')
print(file_object.read())
Out[3]: ---------------------------------------------------------------------------
UnsupportedOperation Traceback (most recent call last)
<ipython-input-10-976007c6d34d> in <module>
2 with open(path, encoding = 'utf-8', mode = 'w') as file_object:
3 file_object.write('《手把手陪您学Python》1——为什么要学Python?')
----> 4 print(file_object.read())
UnsupportedOperation: not readable
当我们对刚刚写入的文件执行read()方法时,为什么会出现不可读的错误信息呢?
这是因为我们刚才打开文件时使用的是“w”,也就是只写模式,在这种模式下,是不能够读取文件的。
那么,我们就改变一下打开文件的模式,选择“w+”,也就是读写模式再试试。
In [4]: path = 'lesson/text/blank.txt'
with open(path, encoding = 'utf-8', mode = 'w+') as file_object:
file_object.write('《手把手陪您学Python》1——为什么要学Python?')
print(file_object.read())
Out[4]:
当文件打开的模式从“只写”变成了“读写”以后,确实没有再报不可读的错误模式,说明我们选择的打开模式没有问题。但是为什么输出的结果确实一个空字符,而不是我们刚刚写入的内容呢?
这是因为,无论是文件的读取还是写入,都是按照指针的位置来操作的。在上一篇中,read()整个文件之后,指针的位置就移动到了文件的末尾,所以无法再进行读取了。
写入时也是一样。当写入操作完成后,指针也同样移动到了文件的末尾,当再使用read()读取文件时,也一样不会有返回值。
那么如何才能读取出我们刚刚写入的内容呢?
这就需要用到我们上节课学习的方法seek()。利用seek()方法,将指针移动到文件的开头,这样就可以读取我们刚刚写入的内容了。
In [5]: path = 'lesson/text/blank.txt'
with open(path, encoding = 'utf-8', mode = 'w+') as file_object:
file_object.write('《手把手陪您学Python》1——为什么要学Python?')
file_object.seek(0)
print(file_object.read())
Out[5]: 《手把手陪您学Python》1——为什么要学Python?
3、读写模式r+
除了可以使用“w+”进行读写以外,还可以使用“r+”进行读写操作。上面的程序改为使用“r+”模式也是一样的效果。
In [6]: path = 'lesson/text/blank.txt'
with open(path, encoding = 'utf-8', mode = 'r+') as file_object:
file_object.write('《手把手陪您学Python》1——为什么要学Python?')
file_object.seek(0)
print(file_object.read())
Out[6]: 《手把手陪您学Python》1——为什么要学Python?
那么“w+”和“r+”的区别是什么?就是使用“w+”时,如果文件不存在则会自动创建。而使用“r+”时,如果文件不存在则会报错。所以大家尽量使用“w+”模式。
4、写入多行
由于write()方法不会在写入的文本末尾自动加入换行符,如果不自行添加换行的转义字符的话,即使是两行write()命令的写入结果,也是紧紧相连的。
In [7]: path = 'lesson/text/blank.txt'
with open(path, encoding = 'utf-8', mode = 'w+') as file_object:
file_object.write('《手把手陪您学Python》1——为什么要学Python?')
file_object.write('《手把手陪您学Python》2——Python的安装')
file_object.seek(0)
print(file_object.read())
Out[7]: 《手把手陪您学Python》1——为什么要学Python?《手把手陪您学Python》2——Python的安装
所以,如果要写入多行,就要在写入的文本后面增加转义字符进行换行。
In [8]: path = 'lesson/text/blank.txt' # 将文件写入blank.txt
with open(path, encoding = 'utf-8', mode = 'w+') as file_object:
file_object.write('《手把手陪您学Python》1——为什么要学Python?\n')
file_object.write('《手把手陪您学Python》2——Python的安装\n')
file_object.seek(0)
print(file_object.read().rstrip()) # 使用rstrip()避免出现空行
Out[8]: 《手把手陪您学Python》1——为什么要学Python?
《手把手陪您学Python》2——Python的安装
除此之外,还有一种写入多行的办法,就是使用writelines()方法。
将要写入的内容通过列表的方式写入到目标文件中,列表中的每一个元素,就是要写入目标文件中的内容。但如果要实现换行,也需要在期望换行的位置增加转移字符。
In [9]: path = 'lesson/text/blank.txt'
with open(path, encoding = 'utf-8', mode = 'w+') as file_object:
file_object.writelines(['《手把手陪您学Python》1——为什么要学Python?\n', '《手把手陪您学Python》2——Python的安装\n'])
file_object.seek(0)
print(file_object.read().rstrip())
Out[9]: 《手把手陪您学Python》1——为什么要学Python?
《手把手陪您学Python》2——Python的安装
5、使用附加模式写入
刚才介绍的方法,无论是“w”模式、“w+”模式还是“r+”模式,都是从文件的起始位置写入,包括将同名文件覆盖后写入。
如果我们要保留原文件的内容,在原文件的末尾继续写入,就需要使用附加模式“a”以及“a+”。
在这种打开模式下,文件会自动将指针移动到原文件的末尾,所有添加的内容都会添加到原文件的末尾处,而不会覆盖文件原来的内容。
In [10]: path = 'lesson/text/blank.txt'
with open(path, encoding = 'utf-8', mode = 'a+') as file_object:
file_object.write('《手把手陪您学Python》3——Pycharm的安装和配置')
file_object.seek(0)
print(file_object.read())
Out[10]: 《手把手陪您学Python》1——为什么要学Python?
《手把手陪您学Python》2——Python的安装
《手把手陪您学Python》3——Pycharm的安装和配置
为了能够读取出我们使用附加模式写入的内容,实例中采用“a+”模式,如果使用“a”模式打开,则只能通过打开写入的文件去验证。
“a”“a+”与“w”“w+”的模式比较类似,都是如果文件不存在就创建,如果文件存在就继续使用原文件。只不过是写入的位置不同,“a”“a+”会从文件的末尾以新增的方式写入,而“w”“w+”会将原文件覆盖,从头开始写入。
以上就是文件写入的几种方法介绍,希望大家能够了解不同打开方式对文件写入方式的影响,同时理解Python写入文件的基本原理。这里我们用表格的形式再总结一下:
模式 | 操作 | 若存在同名文件 | 若不存在同名文件 |
r | 只读 | 读取 | 报错 |
r+ | 可读可写 | 覆盖写入 | 报错 |
w | 只写 | 覆盖写入 | 创建 |
x | 只写 | 报错 | 创建 |
w+ | 可读可写 | 覆盖写入 | 创建 |
a | 只写 | 末尾追加写入 | 创建 |
a+ | 可读可写 | 末尾追加写入 | 创建 |
下一篇我们将要学习存储数据的方法,存储数据其实也是写入,但这里主要是说按照特定的格式存储并读取数据的方法,敬请关注。
感谢阅读本文!如有任何问题,欢迎留言,一起交流讨论^_^
要阅读《手把手陪您学Python》系列文章的其他篇目,请关注公众号点击菜单选择,或点击下方链接直达。
《手把手陪您学Python》3——PyCharm的安装和配置
《手把手陪您学Python》5——Jupyter Notebook
For Fans:关注“亦说Python”公众号,回复“手34”,即可免费下载本篇文章所用示例语句。
