打开与关闭文件
文件操作是程序与外部世界交互的基础。Python 用内置的 open() 函数打开文件,返回一个文件对象,然后通过这个对象读写数据。操作完成后必须关闭文件,释放系统资源。
open() 函数
f = open("data.txt", "r")
content = f.read()
f.close()
open(filename, mode) 的参数:
filename:文件路径(相对或绝对)mode:打开模式,默认为"r"(只读文本)
常用模式:
| 模式 | 含义 |
|---|---|
"r" | 只读(默认) |
"w" | 只写,会截断文件(清空原有内容) |
"a" | 追加,在文件末尾写入 |
"r+" | 读写,不截断 |
"w+" | 读写,先截断 |
"a+" | 读写,追加模式 |
"rb" | 二进制只读 |
"wb" | 二进制只写 |
"ab" | 二进制追加 |
文本模式 vs 二进制模式
Python 2 中,文本模式和二进制模式有本质区别:
# 文本模式(默认)
f = open("data.txt", "r")
content = f.read() # 返回 str(字节串)
# 二进制模式
f = open("data.bin", "rb")
data = f.read() # 返回 str(字节串,与文本模式相同!)
⚠️ Python 2 中,文本模式和二进制模式都返回 str(字节串)。区别仅在于:
- 文本模式:Windows 上会把
\r\n转换为\n - 二进制模式:不做任何转换,原样返回
这与 Python 3 完全不同(Python 3 文本模式返回 str(Unicode),二进制模式返回 bytes)。
关闭文件
文件对象占用操作系统资源,用完后必须关闭:
f = open("data.txt", "r")
data = f.read()
f.close()
忘记关闭会导致:
- 资源泄漏(打开文件数达到系统上限后无法再打开)
- 数据丢失(写入操作可能缓存在内存中,关闭时才刷到磁盘)
- Windows 上文件被锁定,其他程序无法访问
安全关闭:try-finally
确保文件一定被关闭,用 try-finally:
f = open("data.txt", "r")
try:
data = f.read()
process(data)
finally:
f.close() # 无论是否异常,都会执行
更简洁的写法是用 with 语句(上下文管理器),下一节详细讲解。
文件编码
Python 2 中,文本模式默认使用系统编码(Windows 通常是 mbcs,Linux 通常是 UTF-8)。如果文件编码与系统编码不一致,需要手动解码:
# 读取 UTF-8 编码的文件
f = open("utf8_file.txt", "r")
byte_data = f.read() # str(字节串)
text = byte_data.decode("utf-8") # 手动解码为 unicode
f.close()
# 写入 UTF-8 编码的文件
text = u"你好,世界"
f = open("utf8_file.txt", "w")
f.write(text.encode("utf-8")) # 手动编码为字节串
f.close()
更优雅的方式是用 codecs 模块:
import codecs
# 自动处理编码
f = codecs.open("utf8_file.txt", "r", "utf-8")
text = f.read() # 直接返回 unicode
f.close()
f = codecs.open("utf8_file.txt", "w", "utf-8")
f.write(u"你好,世界") # 自动编码写入
f.close()
文件路径
# 相对路径(相对于当前工作目录)
f = open("data.txt", "r")
# 绝对路径
f = open("/home/user/data.txt", "r") # Linux
f = open("C:\\Users\\User\\data.txt", "r") # Windows
# 原始字符串(Windows 路径推荐)
f = open(r"C:\Users\User\data.txt", "r")
# 跨平台路径拼接
import os
path = os.path.join("folder", "subfolder", "file.txt")
# Linux: folder/subfolder/file.txt
# Windows: folder\\subfolder\\file.txt
常见错误
文件不存在:
f = open("nonexistent.txt", "r") # IOError: [Errno 2] No such file or directory
权限不足:
f = open("/etc/passwd", "w") # IOError: [Errno 13] Permission denied
忘记关闭:
def read_file(path):
return open(path, "r").read() # 文件对象泄漏!
正确做法:
def read_file(path):
with open(path, "r") as f:
return f.read() # with 自动关闭