2.27. 读写¶
文件存放在磁盘上;Python 通过 open() 访问它们,该函数返回一个文件对象,其方法用于读写底层的字节。
2.27.1. open 与模式¶
第一个参数是路径;第二个参数是模式 —— 一个简短的字符串,告诉 Python 这个文件将如何被使用:
"r"—— 读取(默认)。打开一个已存在的文件以供读取。"w"—— 写入。创建一个新文件,或将一个已存在的文件截断为空。"a"—— 追加。以在文件末尾写入的方式打开文件,且不截断。在上述任意模式后追加
"b"("rb"、"wb"、"ab")—— 二进制模式。此时文件内容是bytes而非str。
f = open("notes.txt", "r")
text = f.read()
f.close()
2.27.2. 使用上下文管理器¶
如果 open() 与 close 之间有任何代码抛出异常,上面的写法就会泄漏文件句柄。解决办法是使用 with 语句(参见 上下文管理器):
with open("notes.txt") as f:
text = f.read()
# f is closed here, even if read() failed
这是标准写法 —— 每次都这样写。
2.27.3. 读取¶
文件对象支持几种读取方式:
io.IOBase.read()—— 读取整个文件(或 N 个字节)并将其作为单个字符串(或字节对象)返回。io.IOBase.readline()—— 读取一行,包括末尾的"\n"。直接迭代文件会一次产出一行,其内存占用比一次性读取整个文件要小得多。
with open("log.txt") as f:
for line in f:
print(line.rstrip())
str.rstrip() 会在打印前移除末尾的换行符,这样输出就不会出现双倍行距。
2.27.4. 写入¶
以 "w" 模式打开文件,并使用 io.IOBase.write():
with open("out.txt", "w") as f:
f.write("hello\n")
f.write("world\n")
io.IOBase.write() 不会添加换行符 —— 它精确地写入你给它的字节(在文本模式下则是字符)。
2.27.5. 文本与二进制¶
文本模式(默认,即不带 "b" 的 "r" / "w")会使用默认编码把读入的字节解码为 str,并把写出的 str 编码回字节。用它来处理配置、日志、JSON —— 任何本身就是文本的内容。
二进制模式("rb" / "wb")会跳过解码步骤并返回 bytes。用它来处理图像、按结构打包的记录、网络抓包 —— 任何每个字节都至关重要且文件不可供人阅读的内容。
2.27.6. 列出与删除文件¶
os 模块暴露了那些不在文件对象本身上的文件系统操作:
os.listdir()—— 返回一个目录中名称的列表。os.remove()—— 删除一个文件。os.rename()—— 重命名一个文件。os.stat()—— 文件元数据(大小、修改时间……)。os.mkdir()—— 创建一个新目录。
import os
for name in os.listdir("/"):
print(name)
当文件或目录可能不存在时,请在这些操作周围捕获 OSError —— 在实际脚本中,这类操作是异常常见的出现之处之一。