应优先使用io.stringio替代字符串拼接,避免循环中频繁+=导致性能骤降;逐行处理大文件用for line in f而非readlines()防oom;统一用open(..., encoding=...)而非codecs.open();正则匹配多行文本时用re.search()而非re.match(),并预编译pattern。

用 io.StringIO 替代字符串拼接做中间缓存
频繁用 += 拼接大量文本,会触发多次内存分配和复制,性能断崖式下跌。尤其在循环中构建日志、CSV 片段或模板填充结果时,这是最常被忽略的性能黑洞。
-
io.StringIO是纯内存中的文本流,写入是 O(1) 平摊操作,适合累积 → 一次性取值 - 别在循环里反复调用
.getvalue(),它每次返回新字符串副本;攒完再取 - 如果最终要写文件,直接用
shutil.copyfileobj(stringio, file_obj),避免中间字符串生成
from io import StringIO
buf = StringIO()
for line in lines:
buf.write(line.strip() + "\n")
result = buf.getvalue() # 只调用一次读大文件别用 readlines(),改用迭代器逐行处理
readlines() 会把整个文件加载进内存,哪怕只是想过滤几行。GB 级日志一读就 OOM,错误信息通常是 MemoryError 或进程被系统 kill。
- 直接
for line in f:是最安全的逐行迭代,底层用缓冲 I/O,内存占用恒定 - 需要跳过头部或按块读取?用
itertools.islice(f, skip_n)或手动f.readline() - 如果必须分块(比如每 1000 行一批),用
itertools.batched(f, 1000)(Python 3.12+),旧版本手写生成器更稳
codecs.open() 已过时,统一用内置 open() 的 encoding 参数
用 codecs.open() 处理中文或特殊编码,容易漏掉 errors 策略,导致 UnicodeDecodeError 崩溃。而且它返回的流对象行为和内置 open() 不完全一致,混用易出 bug。
将产品展示、购物管理、资金管理等功能相结合,并提供了简易的操作、丰富的功能和完善的权限管理,为用户提供了一个低成本、高效率的网上商城建设方案包含PowerEasy CMS普及版,主要功能模块:文章频道、下载频道、图片频道、留言频道、采集管理、商城模块、商城日常操作模块500个订单限制(超出限制后只能查看和删除,不能进行其他处理) 无订单处理权限分配功能(只有超级管理员才能处理订单)
- 所有场景优先用
open(path, encoding="utf-8", errors="replace") -
errors别只写"ignore"—— 丢数据不报错,后期难排查;"replace"至少留个 提示 - 读二进制再解码?除非要精细控制字节边界,否则没必要;
open(..., "rb")后手动.decode()容易忘记指定errors
正则处理多行文本,小心 re.match() 和 re.search() 的行为差异
用 re.match() 找日志块、配置段落时,发现总匹配不上,其实是它只从字符串开头匹配,而实际文本往往有前导空格或 BOM。这不是正则写错了,是函数选错了。
立即学习“Python免费学习笔记(深入)”;
- 要找任意位置的模式,无条件用
re.search();match()仅用于“必须从头开始”的校验场景 - 跨行匹配记得加
re.DOTALL标志,否则.不匹配换行符 - 对大文本反复调用
re.findall()?先用re.compile()编译正则对象,避免重复解析开销
pattern = re.compile(r"ERROR.*?END", re.DOTALL)
for match in pattern.finditer(large_text):
print(match.group())文本流处理的真正难点不在语法,而在边界:编码怎么兜底、内存怎么不爆、换行符在不同系统下是否被正确识别——这些地方不显眼,但一出问题就是线上事故。









