Python-06:文件操作
Python 中对文件的操作有很多种常见的操作包括创建、删除、修改权限、读取、写入等这些操作可大致分为以下 2 类:
- 删除、修改权限:作用于文件本身属于系统级操作。
- 写入、读取:是文件最常用的操作作用于文件的内容属于应用级操作。
文件的应用级操作可以分为以下 3 步每一步都需要借助对应的函数实现:
- 打开文件:使用 open( ) 函数该函数会返回一个文件对象。
- 对已打开文件做读/写操作:读取文件内容可使用 read( )、readline( ) 以及 readlines( ) 函数;向文件中写入内容可以使用 write( ) 函数。
- 关闭文件:完成对文件的读/写操作之后最后需要关闭文件可以使用 close( ) 函数。
1. 创建 / 打开文件
1.1 基本语法
open( ) 函数用于创建或打开指定文件该函数的常用语法格式下:
1 | file = open(file_name [,mode='r' [,buffering=-1 [,encoding=None] ] ]) |
此格式中用 [ ] 括起来的部分为可选参数。其中常用参数所代表的含义如下:
- file:表示要创建的文件对象。
- file_name:要创建或打开文件的文件名称该名称要用引(单引号或双引号都可以)括起来。
- mode:可选参数用于指定文件的打开模式,如果不写则默认以只读(r)模式打开文件。
- encoding:手动设定打开文件时所使用的编码格式不同平台的 ecoding 参数值也不同以 Windows 为例,其默认为 cp936(实际上就是 GBK 编码)。
open 函数支持的文件打开模式:
| 模式 | 意义 | 注意事项 |
|---|---|---|
| r | 只读模式打开文件,读文件内容的指针会放在文件的开头。 | 操作的文件必须存在。 |
| rb | 以二进制格式、采用只读模式打开文件,读文件内容的指针位于文件的开头,一般用于非文本文件,如图片文件、音频文件等。 | |
| r+ | 打开文件后,既可以从头读取文件内容,也可以从开头向文件中写入新的内容,写入的新内容会覆盖文件中等长度的原有内容。 | |
| rb+ | 以二进制格式、采用读写模式打开文件,读写文件的指针会放在文件的开头,通常针对非文本文件(如音频文件)。 | |
| w | 以只写模式打开文件,若该文件存在,打开时会清空文件中原有的内容。 | 若文件存在,会清空其原有内容(覆盖文件);反之,则创建新文件。 |
| wb | 以二进制格式、只写模式打开文件,一般用于非文本文件(如音频文件)。 | |
| w+ | 打开文件后,会对原有内容进行清空,并对该文件有读写权限。 | |
| wb+ | 以二进制格式、读写模式打开文件,一般用于非文本文件。 | |
| a | 以追加模式打开一个文件,对文件只有写入权限,如果文件已经存在,文件指针将放在文件的末尾(即新写入内容会位于已有内容之后);反之,则会创建新文件。 | |
| ab | 以二进制格式打开文件,并采用追加模式,对文件只有写权限。如果该文件已存在,文件指针位于文件末尾(新写入文件会位于已有内容之后);反之,则创建新文件。 | |
| a+ | 以读写模式打开文件;如果文件存在,文件指针放在文件的末尾(新写入文件会位于已有内容之后);反之,则创建新文件。 | |
| ab+ | 以二进制模式打开文件,并采用追加模式,对文件具有读写权限,如果文件存在,则文件指针位于文件的末尾(新写入文件会位于已有内容之后);反之,则创建新文件。 |
1.2 上下文管理器
有时候我们 open 完文件后,可能会忘记关闭文件。而在 Python 中,使用 with as 语句可以操作上下文管理器(context manager),它能够帮助我们自动分配并且释放资源。
with as 语句的基本语法格式为:
1 | with 表达式 [as target]: |
此格式中,用 [ ] 括起来的部分可以使用,也可以省略。其中,target 参数用于指定一个变量,该语句会将 expression 指定的结果保存到该变量中。
1 | with open('open_file.txt', 'r') as f: |
2. 读取文件
2.1 读取函数
Python 提供了如下 3 种函数,它们都可以帮我们实现读取文件中数据的操作:
- read( ) 函数:逐个字节或者字符读取文件中的内容
- readline( ) 函数:逐行读取文件中的内容
- readlines( ) 函数:一次性读取文件中多行内容
2.1.1 read( ) 函数
read( ) 函数的基本语法格式如下:
1 | file.read([size]) |
其中,file 表示已打开的文件对象;size 作为一个可选参数,用于指定一次最多可读取的字符(字节)个数,如果省略,则默认一次性读取所有内容。
示例 1:读取文本
1 | # open_file.txt |
示例 2:读取图片
1 | # 以二进制形式打开指定文件 |
示例 3:rstrip 消除
我们还可以将 open 的文件或 read 读取到的数据赋值给一个变量,然后通过这个变量进行操作。
1 | f = open("open_file.txt", 'r') |
read( ) 函数抛出 UnicodeDecodeError 异常的解决方法
在使用 read( ) 函数时,如果 Python 解释器提示 UnicodeDecodeeError 异常或者显示为乱码,其原因在于目标文件使用的编码格式和 open( ) 函数打开该文件时使用的编码格式不匹配。
例如现在我有一段脚本用来获取并打印 ping www.baidu.com 返回的数据信息。
1 | import subprocess |
我们在 cmd 中 ping 这个网址,就会返回一些数据信息:
但是我们运行上面的脚本打印出来的信息确实一些字节流,看不懂什么意思。
这就需要我们对返回的数据进行解码操作,我先尝试用 utf-8 进行解码。
1 | import subprocess |
却发现运行时返回了 UnicodeDecodeeError 的异常。
这是因为返回的数据格式不是 utf-8,即编码格式不匹配。因此,我们可以使用 chardet 库中的 detect 检测函数来检测返回的数据的编码格式是什么。
1 | import subprocess |
这时候我们就可以获取到返回数据的编码格式,即为 GB2312 格式。
因此,我们在解码的时候指定用 GB2312 格式即可返回解码成功后的数据。
1 | import subprocess |
2.1.2 readline( ) 函数
readline( ) 函数用于读取文件中的一行,包含最后的换行符 “\n”。此函数的基本语法格式为:
1 | file.readline([size]) |
其中,file 为打开的文件对象;size 为可选参数,用于指定读取每一行时,一次最多读取的字符(字节)数。
1 | f = open("open_file.txt") |
如果不想打印出空行,则可以在后面通过 end 指定结尾不是换行符。
1 | f = open("open_file.txt") |
注意 readline 中传入的参数不是指定读取的行数,而是字节数。
1 | f = open("open_file.txt") |
另外,我们也可以通过 for 循环遍历获取文件中的每行数据。
1 | filename = 'open_file.txt' |
2.1.3 readlines( ) 函数
readlines( ) 函数用于读取文件中的所有行,它和调用不指定 size 参数的 read( ) 函数类似,只不过该函数返回是一个字符串列表,其中每个元素为文件中的一行内容。
readlines( ) 函数的基本语法格式如下:
1 | file.readlines() |
其中,file 为打开的文件对象。和 read( )、readline( ) 函数一样,它要求打开文件的模式必须为可读模式(包括 r、rb、r+、rb+ 4 种)。
1 | f = open("open_file.txt") |
2.2 读取大文件
Python 读取文件一般是利用 open( ) 函数以及 read( ) 函数来完成,但该方式仅适合读取小文件。因为调用 read( ) 会一次性读取文件的全部内容,调用 readlines( ) 一次读取所有内容并按行返回 list。如果文件过大,如 10G,会造成 MemoryError 内存溢出,正确的做法:可以反复调用 read(size) 方法,每次指定读取 size 个字节的内容。
处理大文件核心思路: 通过参数指定每次读取的大小长度,这样就避免了因为文件太大读取出问题。
1 | while True: |
2.3 fileinput 模块
Python 提供了 fileinput 模块,通过该模块中的 input( ) 函数,我们能同时打开指定的多个文件,还可以逐个读取这些文件中的内容。
fileinput 模块中 input( ) 该函数的语法格式如下:
1 | fileinput.input(files="filename1, filename2, ...", inplace=False, backup=", bufsize=0, mode='r', openhook=None) |
其中,各个参数的含义如下:
- files:多个文件的路径列表。
- inplace:用于指定是否将标准输出的结果写回到文件,此参数默认值为 False。
- backup:用于指定备份文件的扩展名。
- bufsize:指定缓冲区的大小,默认为 0。
- mode:打开文件的格式,默认为 r(只读格式)。
- openhook:控制文件的打开方式,例如编码格式等。
1 | import fileinput |
如果我们对文件进行修改,例如下面将 open_file.txt 里的数据转换为大写字母,则可以通过 backup 参数对文件进行备份。下面在修改完 open_file.txt 里面的数据后,也会同时生成一个 open_file.txt.bak 的文件,存储修改之前的数据,避免一些误操作导致文件被破坏。
1 | import fileinput |
2.4 linecache 模块
除了可以借助 fileinput 模块实现读取多个文件外,Python 还提供了 linecache 模块。和前者不同,linecache 模块擅长读取指定文件中的指定行。
换句话说,如果我们想读取某个文件中指定行包含的数据,就可以使用 linecache 模块。
1 | import linecache |
3. 写文件
我们再回顾一下上面的内容,调用 open( ) 时提供两个实参,第一个是要打开的文件的名称,第二个则是告诉 Python 进行的模式,常见模式为读取模式(’r’)、写入模式(’w’)、附加模式(’a’)或读写模式(’r+’)。如果省略了模式实参,Python 将以默认的只读模式打开文件。
Tips:
写入模式会再返回文件对象前清空该文件的内容,如果想在文件后直接添加内容而不是覆盖原有的内容,可以以附加模式打开文件。
3.1 write( ) 函数
Python 中的文件对象提供了 write( ) 函数,可以向文件中写入指定内容。
该函数的语法格式如下:
1 | file.write(string) |
其中:
- file 表示已经打开的文件对象
- string 表示要写入的字符串
1 | f = open("test01.txt", 'w') |
3.2 writelines( ) 函数
Python 的文件对象中,不仅提供了 write( ) 函数,还提供了 writeliines( ) 函数,可以实现将字符串列表写入文件中。一般配合着 readlines( ) 函数使用,可以快速的将文件中的数据复制到其它文件中。
1 | f_r = open("test01.txt", 'r') |
Tips:
Python 只能将字符串写入文本文件,如果要将数值数据存储到文本文件中,必须先使用函数 str( ) 将其转换为字符串格式。
3.3 json.dump( ) 和 json.load( )
- json.dump( )
在 Python 中,json.dump() 函数用于将数据对象序列化为 JSON 格式并将其写入文件。例如,下面我们可以将 numbers 列表存储于 numbers.json 文件中。
1 | import json |
- json.load( )
json.load() 函数则用于从文件中读取 JSON 格式的数据并将其反序列化为 Python 对象。例如,下面我又将刚才存入 numbers.json 中的数据读取出来。
1 | import json |
4. 文件指针
实现对文件指针的移动,文件对象提供了 tell( ) 函数和 seek( ) 函数。tell( ) 函数用于判断文件指针当前所处的位置,而 seek( ) 函数用于移动文件指针到文件的指定位置。
4.1 tell( ) 函数
由于 read 函数每次调用完后,文件的指针会停留在当前读取完的数据的位置,下次再次读取时会从上次读取完的位置继续读取。而通过 tell( ) 函数可以判断当前指针处于哪个位置,tell( ) 函数的用法很简单,其基本语法格式如下:
1 | file.tell() |
现在我通过 read 函数分别读取 1 个字节以及 2 个字节的数据,然后调用 tell 函数可以发现当前文件的指针停留在了第 3 个字节的位置。
1 | f = open('open_file.txt', 'r') |
4.2 seek( ) 函数
上面可知,文件读取完后指针不会重置,因此下次想从头或者其它位置开始读取,则可以使用 seek( ) 函数将文件指针移动至指定位置,该函数的语法格式如下:
1 | file.seek(offset[, whence]) |
接着上面的案例,我们可以通过 seek 函数将函数指针移至开头的位置,这样下次读取时又会从头开始读取。
1 | f = open('open_file.txt', 'r') |









