Python学习日记9

Python学习日记9 文件操作11.1 文件操作概述11.1.1 为什么需要文件操作程序运行时数据存储在内存中但程序结束后数据就会丢失。文件操作让程序能够持久化存储将数据保存到磁盘程序重启后仍然存在数据交换读取外部数据数据集、配置文件导出结果处理大型数据逐行读取避免一次性加载到内存11.1.2 文件操作的基本流程# 1. 打开文件 f open(filename.txt, r) # 2. 读取或写入 content f.read() f.write(Hello) # 3. 关闭文件 f.close()11.2 打开文件open()函数11.2.1 基本语法f open(somefile.txt) # 只读模式默认 f open(somefile.txt, r) # 显式指定只读 f open(somefile.txt, w) # 写入模式覆盖 f open(somefile.txt, a) # 追加模式 f open(somefile.txt, x) # 独占创建模式文件已存在时报错11.2.2 文件模式rvswr可读可写不截断文件从头开始读写w可读可写但会清空文件截断# 文本模式默认——自动解码/编码 f open(text.txt, r) # 读取文本默认 UTF-8 f open(text.txt, w) # 写入文本 # 二进制模式——读写原始字节 f open(image.png, rb) # 读取二进制文件 f open(image.png, wb) # 写入二进制文件11.2.3 指定编码# 指定编码读取 f open(text.txt, r, encodingutf-8) f open(text.txt, r, encodinggbk) # 错误处理 f open(text.txt, r, encodingascii, errorsignore)11.2.4 文件路径# 相对路径 f open(data.txt) # 当前目录 f open(data/subdata.txt) # 子目录 # 绝对路径 f open(/home/user/data.txt) # Linux/macOS f open(C:\\Users\\user\\data.txt) # Windows注意转义 f open(rC:\Users\user\data.txt) # 使用原始字符串11.3 读写文件11.3.1 读取文本f open(data.txt, r, encodingutf-8) # 读取全部内容 content f.read() # 返回整个文件内容的字符串 # 读取指定字符数 content f.read(100) # 读取前100个字符 # 读取一行 line f.readline() # 返回一行包含换行符 # 读取所有行 lines f.readlines() # 返回列表每行一个元素 f.close()示例逐行读取f open(data.txt, r, encodingutf-8) for line in f: # 文件对象本身就是可迭代的 line line.strip() # 去除末尾换行符 print(line) f.close()11.3.2 写入文本f open(data.txt, w, encodingutf-8) # 写入字符串 f.write(Hello, world!\n) # 写入多行接收字符串列表 lines [Line 1\n, Line 2\n, Line 3\n] f.writelines(lines) f.close()11.3.3 二进制文件# 读取二进制文件 f open(image.png, rb) data f.read() # bytes 类型 f.close() # 写入二进制文件 f open(output.png, wb) f.write(data) # 写入 bytes f.close()11.4 关闭文件的重要性11.4.1 为什么要关闭确保数据写入磁盘Python 会缓冲写入数据关闭时才会真正写入释放系统资源每个进程有文件打开数量限制避免文件锁定问题其他程序可能无法访问11.4.2 缓冲问题演示# 写入后立即关闭 f open(test.txt, w) f.write(Hello) f.close() # 文件内容正常写入 # 写入后不关闭 f open(test.txt, w) f.write(Hello) # 此时文件可能为空数据在缓冲区11.4.3flush()—— 强制刷新f open(test.txt, w) f.write(Hello) f.flush() # 强制将缓冲区数据写入磁盘 # 即使不关闭数据也已写入11.5 上下文管理器with语句推荐11.5.1 基本用法with语句会自动关闭文件即使发生异常也不会遗漏。with open(data.txt, r, encodingutf-8) as f: content f.read() print(content) # 文件在 with 块结束后自动关闭无需显式调用 close()对比传统方式# 传统方式容易忘记关闭 f open(data.txt, r) try: content f.read() finally: f.close() # 必须手动关闭 # with 方式更简洁可靠 with open(data.txt, r) as f: content f.read()11.5.2 处理多个文件# 同时打开两个文件复制文件 with open(source.txt, r) as src, open(dest.txt, w) as dst: for line in src: dst.write(line)11.5.3 上下文管理器的工作原理上下文管理器必须实现两个方法__enter__()进入with块时调用返回值赋给as后的变量__exit__(exc_type, exc_val, exc_tb)退出时调用处理异常和清理class FileContext: def __init__(self, filename, mode): self.filename filename self.mode mode self.file None def __enter__(self): self.file open(self.filename, self.mode) return self.file def __exit__(self, exc_type, exc_val, exc_tb): if self.file: self.file.close() # 返回 False 表示不抑制异常 return False # 使用 with FileContext(test.txt, w) as f: f.write(Hello)11.6 文件定位seek()和tell()11.6.1tell()—— 获取当前位置with open(data.txt, r) as f: print(f.tell()) # 0文件开头 f.read(5) print(f.tell()) # 5已读取5个字符11.6.2seek()—— 移动文件指针# seek(offset, whence) # whence: 0文件开头默认1当前位置2文件末尾 with open(data.txt, r) as f: # 跳到第10个字符位置 f.seek(10) # 从当前位置向后移动5个字符 f.seek(5, 1) # 跳到文件末尾前10个字符处 f.seek(-10, 2)示例读取文件的最后一行with open(data.txt, rb) as f: # 二进制模式 # 跳到文件末尾 f.seek(-100, 2) # 向前100字节 data f.read().decode(utf-8) last_line data.strip().split(\n)[-1] print(last_line)11.7 标准流11.7.1 三个标准流Python 提供了三个标准流对象类似文件对象import sys # 从标准输入读取 text sys.stdin.read() print(Read:, text) # 写入标准输出 sys.stdout.write(Hello, stdout!\n) # 写入标准错误 sys.stderr.write(Error message\n)11.7.2 重定向标准输出import sys # 将输出重定向到文件 with open(output.txt, w) as f: sys.stdout f print(This goes to file) # 不会显示在控制台 # 恢复标准输出 sys.stdout sys.__stdout__ print(This goes to console)11.8 文件模式详解11.8.1 文本模式 vs 二进制模式文本模式默认自动处理编码/解码字符 ↔ 字节自动处理换行符转换\n↔ 平台换行符读写str类型二进制模式不进行编码转换不处理换行符读写bytes类型# 文本模式默认 with open(data.txt, r) as f: content f.read() # str 类型 print(type(content)) # class str # 二进制模式 with open(data.txt, rb) as f: content f.read() # bytes 类型 print(type(content)) # class bytes11.8.2 换行符处理文本模式下的换行符转换读取时将\r\n和\r转换为\n写入时将\n转换为系统默认换行符os.linesep# 禁用换行符转换 with open(data.txt, r, newline) as f: line f.readline() # 保留原始换行符 # 指定换行符 with open(data.txt, r, newline\r\n) as f: line f.readline()11.9 迭代文件内容11.9.1 按字符读取def process(char): print(char, end) with open(data.txt, r) as f: char f.read(1) while char: # 文件末尾返回空字符串 process(char) char f.read(1) # 更简洁的方式 with open(data.txt, r) as f: for char in f.read(): # read() 将整个文件读入内存 process(char)11.9.2 按行读取推荐# 方式1直接迭代文件对象 with open(data.txt, r) as f: for line in f: line line.rstrip(\n) # 去除换行符 process(line) # 方式2readline 循环 with open(data.txt, r) as f: while True: line f.readline() if not line: break process(line.rstrip(\n))11.9.3 读取所有行到列表# 适合小型文件 with open(data.txt, r) as f: lines f.readlines() # 列表每行一个元素 for line in lines: process(line)11.9.4 使用fileinput处理多个文件import fileinput # 依次处理多个文件 for line in fileinput.input([file1.txt, file2.txt]): print(f{fileinput.filename()}: {line}, end)11.9.5 懒加载 vs 一次性加载11.10 文件操作示例11.10.1 复制文件def copy_file(src, dst): 逐块复制文件适用于大文件 with open(src, rb) as src_f, open(dst, wb) as dst_f: while True: chunk src_f.read(4096) # 每次读取4KB if not chunk: break dst_f.write(chunk) copy_file(source.bin, dest.bin)11.10.2 统计文件单词数def word_count(filename): with open(filename, r, encodingutf-8) as f: text f.read() words text.split() return len(words) print(word_count(data.txt))11.10.3 文件搜索def grep(filename, pattern): 在文件中搜索包含 pattern 的行 with open(filename, r, encodingutf-8) as f: for line in f: if pattern in line: print(line.rstrip(\n)) grep(data.txt, ERROR)11.10.4 CSV 文件处理import csv # 写入 CSV data [ [Name, Age, Score], [Alice, 25, 92], [Bob, 30, 85], ] with open(data.csv, w, newline) as f: writer csv.writer(f) writer.writerows(data) # 读取 CSV with open(data.csv, r) as f: reader csv.reader(f) for row in reader: print(row) # 使用字典读写有表头 with open(data.csv, w, newline) as f: writer csv.DictWriter(f, fieldnames[Name, Age, Score]) writer.writeheader() writer.writerow({Name: Alice, Age: 25, Score: 92}) with open(data.csv, r) as f: reader csv.DictReader(f) for row in reader: print(row[Name], row[Score])