6. 文件读写与 os 库

本章介绍 Python 中基本的文件读写功能,以及 os 标准库。由于涉及到文件操作会使用到文件路径,一般我们在文件读写中都需要加载该库。

[1]:
import os

6.1. 读取文件

使用 open(file, mode='r', encoding=None, ...) 命令来读取文件,其中:

  • file 是文件的(相对或绝对)路径

  • mode 是读写模式,默认是读('r'),也等同于 'rt'

    参数

    解释

    参数

    解释

    'r'

    读取

    'w'

    写入(覆盖原内容)

    'a'

    追加

    'x'

    创建(已存在或失败)

    'b'

    二进制

    't'

    文本文件

    • 注意最后一行的 b/+ 与之前的 r/w/a/x 可以结合使用,比如 rb 是以二进制方式读取文件。

    • 关于 + 参数, w+w+b 将打开文件并清空内容。 模式 r+r+b 将打开文件而不清空内容。

  • encoding 是文件读写时的编码,通常使用的是 'utf-8'。其默认值取决于所在的操作系统。

6.1.1. 普通读取:read() 与 readlines()

文件读取时,需要以 with open(...) as ... 的形式开启一个代码块。

下例给出了读取工作目录下 conf.py 文件的例子,使用了 read() 函数来读入整个文件。

[11]:
# 以下路径等价于 os.path.join(os.getcwd(), "conf.py")
fpath = "conf.py"
with open(fpath, 'r', encoding='utf-8') as f:
    fstr_read = f.read()

fstr_read[:50]  # 显示前50个字符
[11]:
'author = "wklchris"\ncopyright = "wklchris"\nexclude'

注意上列文件中保留了每一行末尾的换行符(\n)。

另一种方式是用 readlines() 将文件读成一个列表,每一行(不含换行符)作为列表的一项。但注意,你必须保证文件的大小不超过可用的内存大小。

[9]:
fpath = "conf.py"
with open(fpath, 'r', encoding='utf-8') as f:
    fstr_readlines = f.readlines()

fstr_readlines[:3]  # 显示前3行
[9]:
['author = "wklchris"\n',
 'copyright = "wklchris"\n',
 "exclude_patterns = ['_build', '**.ipynb_checkpoints']\n"]

再提示一下读者,如果想处理成一个每行为一项的列表,并去掉每行的行末的换行符,可以对 read() 的结果进行 splitlines 操作:

[12]:
fstr_read.splitlines()[:3]
[12]:
['author = "wklchris"',
 'copyright = "wklchris"',
 "exclude_patterns = ['_build', '**.ipynb_checkpoints']"]

6.1.2. 逐行读取:readline()

对于比较大的文件,函数 readline() 允许我们借助 Python 的迭代器特性来控制内存占用。例如:

[14]:
with open (fpath, 'r', encoding='utf-8') as f:
    print(f.readline())
    print(f.readline())
author = "wklchris"
copyright = "wklchris"

因此,我们可以用循环语句来逐行读取:

with open (fpath, 'r', encoding='utf-8') as f:
    while True:
        line = f.readline()
        ...  # Do something
        if not line:
            break

或者一种等效的写法:

with open (fpath, 'r', encoding='utf-8') as f:
    for line in f:
        ...  # Do something

注意

文件流对象(例中的 f)拥有成员函数 tell()seek(),可以移动迭代器”指针“的位置。由于我不推荐使用这种方法,这里就不作介绍了,有兴趣的同学可以自行查阅。

6.2. 写入文件

w 模式代替文件读取中的 r 模式、用 write() 命令代替 read(),即可实现写入:

[15]:
# 向文件中写入全文字符串
with open(fpath, 'w', encoding='utf-8') as f:
    f.write(fstr_read)

类似地,我们也可以使用 writelines() 命令:

[16]:
# 向文件中写入按行(含行尾换行符)划分的字符串列表
with open(fpath, 'w', encoding='utf-8') as f:
    f.writelines(fstr_readlines)