Python 第十九节 文件file操作方法使用详细介绍及注意事项
前言
Python 中文件操作使用详细介绍;
基本语法
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)参数说明:
file: 必需,文件路径(相对或者绝对路径)。
mode: 可选,文件打开模式
buffering: 设置缓冲
encoding: 一般使用utf8
errors: 报错级别
newline: 区分换行符
closefd: 传入的file参数类型
opener: 设置自定义开启器,开启器的返回值必须是一个打开的文件描述符。
1. 文件操作基础
1.1 打开文件
使用 open()
函数打开文件,基本语法:
file = open(filename, mode, encoding)mode 参数说明:'r' - 只读模式(默认)'w' - 写入模式,覆盖文件'a' - 追加模式'x' - 独占创建模式'b' - 二进制模式't' - 文本模式(默认)'+' - 读写模式
1.2 关闭文件
使用 close()
方法或 with
语句:
# 方法1:显式关闭 手动关闭file = open('text.txt', 'r')content = file.read()file.close()# 方法2:使用 with 语句(推荐)with open('text.txt', 'r') as file:content = file.read()# 文件会自动关闭
2. 文件读取操作
2.1 读取整个文件
with open('example.txt', 'r', encoding='utf-8') as file:content = file.read()print(content)
2.2 逐行读取
# 方法1:readline()
with open('text.txt', 'r') as file:line = file.readline()while line:print(line.strip()) # strip() 去除换行符line = file.readline()# 方法2:readlines()
with open('text.txt', 'r') as file:lines = file.readlines()for line in lines:print(line.strip())# 方法3:直接迭代文件对象
with open('text.txt', 'r') as file:for line in file:print(line.strip())
2.3 读取指定字节数
with open('example.txt', 'r') as file:chunk = file.read(100) # 读取前100个字符print(chunk)
3. 文件写入操作
3.1 写入文件
# 覆盖写入
with open('output.txt', 'w', encoding='utf-8') as file:file.write('Hello, World!\n')file.write('这是第二行\n')# 追加写入
with open('output.txt', 'a', encoding='utf-8') as file:file.write('这是追加的内容\n')
3.2 写入多行
lines = ['第一行\n', '第二行\n', '第三行\n']with open('output.txt', 'w') as file:file.writelines(lines)# 或者使用循环
with open('output.txt', 'w') as file:for line in lines:file.write(line)
4. 文件定位
4.1 获取和设置文件位置
with open('test.txt', 'r') as file:# 获取当前位置position = file.tell()print(f'当前位置: {position}')# 读取一些内容content = file.read(10)# 移动到文件开头file.seek(0)# 移动到第50个字节file.seek(50)
5. 实际案例分析
5.1、配置文件读取
def read_config(config_file):config = {}try:with open(config_file, 'r', encoding='utf-8') as file:for line in file:line = line.strip()if line and not line.startswith('#'): # 跳过空行和注释key, value = line.split('=', 1)config[key.strip()] = value.strip()return configexcept FileNotFoundError:print(f"配置文件 {config_file} 不存在")return {}# 使用示例
config = read_config('app.config')
print(config)
5.2、日志记录系统
import datetimeclass Logger:def __init__(self, log_file):self.log_file = log_filedef log(self, level, message):timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')log_entry = f"[{timestamp}] [{level}] {message}\n"with open(self.log_file, 'a', encoding='utf-8') as file:file.write(log_entry)# 使用示例
logger = Logger('app.log')
logger.log('INFO', '应用程序启动')
logger.log('ERROR', '发生了一个错误')
5.3、CSV
文件处理
def read_csv(filename):data = []with open(filename, 'r', encoding='utf-8') as file:headers = file.readline().strip().split(',')for line in file:values = line.strip().split(',')if len(values) == len(headers):row = dict(zip(headers, values))data.append(row)return datadef write_csv(filename, data, headers):with open(filename, 'w', encoding='utf-8') as file:# 写入表头file.write(','.join(headers) + '\n')# 写入数据for row in data:values = [str(row.get(header, '')) for header in headers]file.write(','.join(values) + '\n')# 使用示例
data = [{'name': 'Andy', 'age': '25', 'city': 'Beijing'},{'name': 'Bob', 'age': '30', 'city': 'Shanghai'}
]
write_csv('users.csv', data, ['name', 'age', 'city'])
users = read_csv('users.csv')
print(users)
5.4、大文件处理(内存友好)
def process_large_file(input_file, output_file):"""处理大文件,避免内存溢出"""with open(input_file, 'r', encoding='utf-8') as infile, \open(output_file, 'w', encoding='utf-8') as outfile:for line_num, line in enumerate(infile, 1):# 处理每一行(示例:转换为大写)processed_line = line.upper()outfile.write(processed_line)# 每处理10000行输出进度if line_num % 10000 == 0:print(f'已处理 {line_num} 行')# 使用示例
process_large_file('large_input.txt', 'large_output.txt')
6. 二进制文件操作
6.1 读取和写入二进制文件
# 复制图片文件
with open('source.jpg', 'rb') as source:with open('copy.jpg', 'wb') as destination:chunk_size = 4096while True:chunk = source.read(chunk_size)if not chunk:breakdestination.write(chunk)# 读取二进制数据的特定部分
with open('data.bin', 'rb') as file:# 读取前4个字节(例如:文件签名)signature = file.read(4)print(f'文件签名: {signature}')# 跳转到第100字节file.seek(100)# 读取8个字节data_chunk = file.read(8)
7. 异常处理和最佳实践
7.1 完整的异常处理
def safe_file_operation(filename, operation='read'):try:if operation == 'read':with open(filename, 'r', encoding='utf-8') as file:return file.read()elif operation == 'write':with open(filename, 'w', encoding='utf-8') as file:file.write('一些内容')return Trueexcept FileNotFoundError:print(f"文件 {filename} 不存在")except PermissionError:print(f"没有权限访问文件 {filename}")except UnicodeDecodeError:print(f"文件编码错误,请检查文件编码")except IOError as e:print(f"IO错误: {e}")except Exception as e:print(f"未知错误: {e}")return False# 使用示例
content = safe_file_operation('example.txt', 'read')
7.2 上下文管理器的自定义实现
class SafeFileHandler:def __init__(self, filename, mode, encoding='utf-8'):self.filename = filenameself.mode = modeself.encoding = encodingself.file = Nonedef __enter__(self):try:self.file = open(self.filename, self.mode, encoding=self.encoding)return self.fileexcept Exception as e:print(f"打开文件时出错: {e}")raisedef __exit__(self, exc_type, exc_val, exc_tb):if self.file:self.file.close()if exc_type:print(f"处理文件时发生错误: {exc_val}")return False # 不抑制异常# 使用示例
with SafeFileHandler('example.txt', 'r') as file:content = file.read()print(content)
8. 注意事项
8.1 编码问题
始终指定文件编码,特别是处理中文等非ASCII字符
常见编码:utf-8, gbk, latin-1
使用 errors
参数处理编码错误:
with open('file.txt', 'r', encoding='utf-8', errors='ignore') as f:content = f.read()
8.2 文件路径
使用原始字符串或双反斜杠处理Windows
路径:
path = r'C:\v3-vite\my-ts\9Python\file.txt'# 或path = 'C:\\v3-vite\\my-ts\\9Python\\file.txt'
使用 os.path
模块处理路径:
import ospath = os.path.join('folder', 'subfolder', 'file.txt')
8.3 性能考虑
- 对于大文件,使用
迭代读取而非一次
性读取 - 使用适当的缓冲区大小
- 考虑使用
mmap
模块处理超大文件
8.4 安全考虑
- 验证文件路径,防止路径遍历攻击
- 检查文件大小,防止处理过大的文件
- 使用白名单验证文件类型
import osdef safe_open_file(filepath, allowed_extensions=None):# 规范化路径,防止路径遍历safe_path = os.path.normpath(filepath)# 检查文件扩展名if allowed_extensions:ext = os.path.splitext(safe_path)[1].lower()if ext not in allowed_extensions:raise ValueError(f"不允许的文件类型: {ext}")# 检查文件大小(示例:限制为10MB)if os.path.exists(safe_path):if os.path.getsize(safe_path) > 10 * 1024 * 1024:raise ValueError("文件过大")return open(safe_path, 'r', encoding='utf-8')
这些文件操作技巧,我们可以高效、安全地在Python中处理各种文件操作任务。