处理文本文件时,脚本能否正常运行,往往不只取决于读取和写入语句,还取决于编码是否匹配、空行是否处理得当,以及文件是否被一次性加载到内存。对于日志、配置片段或普通文本,使用上下文管理器逐行读取,通常更稳妥。
打开文本文件时先确定编码
Python 的 open() 函数可以通过 encoding 参数指定文本编码。现在常见的文本文件通常使用 UTF-8,因此可以明确写出:
with open("input.txt", "r", encoding="utf-8") as file:
content = file.read()
这里的 "r" 表示以读取模式打开文件。with 代码块结束后,文件会自动关闭,不需要再调用 close()。
写入文件时同样要指定编码:
with open("output.txt", "w", encoding="utf-8") as file:
file.write("第一行内容n")
file.write("第二行内容n")
"w" 会创建文件;如果文件已经存在,原有内容会被覆盖。如果希望保留原内容并在末尾追加,应使用 "a":
with open("output.txt", "a", encoding="utf-8") as file:
file.write("追加的一行内容n")
如果打开文件时报编码错误,通常说明实际文件编码与代码中的设置不一致。此时应先确认文件的保存编码,再修改 encoding 参数。不能为了让程序继续运行就盲目忽略错误,否则可能得到乱码或损坏的文本。某些带有编码标记的 UTF-8 文件可以尝试使用 utf-8-sig:
with open("input.txt", "r", encoding="utf-8-sig") as file:
content = file.read()
逐行读取,避免一次性加载文件
read() 会把整个文件读取成一个字符串。文件较小时这种方式很直观,但如果文件内容较多,一次性读取会占用较多内存。
更适合文本清洗的写法是直接遍历文件对象:
with open("input.txt", "r", encoding="utf-8") as file:
for line in file:
print(line)
这里的 line 通常已经包含原文件中的换行符。如果直接使用 print(line),可能看到每行之间多出一行空白,因为 print() 自己也会添加换行。可以使用 end="" 保留原来的换行方式:
with open("input.txt", "r", encoding="utf-8") as file:
for line in file:
print(line, end="")
逐行遍历的好处是,程序处理完一行后就可以继续处理下一行,不需要先把整个文件保存到列表中。
判断和处理空行
清理文本时,空行可能表现为几种形式:
- 完全没有内容的行;
- 只包含换行符的行;
- 只包含空格或制表符的行。
使用 line.strip() 可以去除字符串两端的空白字符,再判断结果是否为空:
if line.strip() == "":
continue
这段代码表示:如果当前行去掉空白后没有内容,就跳过这一行。
如果只是想去掉行尾的换行符,而不希望删除行首或行尾的普通空格,可以使用:
clean_line = line.rstrip("rn")
这比 strip() 更适合需要保留原始缩进或空格的文本。两者用途不同:
line.strip() # 判断一行是否只有空白,或同时清理两端空白
line.rstrip("rn") # 只去掉行尾换行符
按条件筛选内容并写入新文件
下面的脚本会完成几个常见任务:
- 读取
input.txt; - 跳过空行;
- 跳过包含指定关键词的行;
- 去掉每行末尾的换行符;
- 将筛选后的内容写入
cleaned.txt; - 全程采用逐行处理,不把整个文件读入内存。
input_path = "input.txt"
output_path = "cleaned.txt"
excluded_keyword = "DEBUG"
with open(input_path, "r", encoding="utf-8") as source:
with open(output_path, "w", encoding="utf-8") as target:
for line in source:
# 跳过空行和只包含空白字符的行
if line.strip() == "":
continue
# 跳过包含指定关键词的行
if excluded_keyword in line:
continue
# 只移除行尾换行符,保留其他内容
clean_line = line.rstrip("rn")
target.write(clean_line + "n")
例如,原文件内容如下:
正常记录一
DEBUG 调试信息
正常记录二
正常记录三
处理后,cleaned.txt 中只会保留:
正常记录一
正常记录二
正常记录三
这里的筛选条件可以根据实际需求修改。例如,筛选包含某个词的行:
if "error" in line.lower():
target.write(line)
lower() 可以让大小写不同的英文内容也被视为相同。若只想保留包含关键词的行,可以反过来写:
if "success" not in line.lower():
continue
target.write(line)
一个更完整的文本清洗脚本
如果希望同时清理首尾空白、跳过空行并过滤关键词,可以把逻辑集中在一个循环中:
input_path = "input.txt"
output_path = "cleaned.txt"
blocked_words = ["DEBUG", "TRACE"]
with open(input_path, "r", encoding="utf-8") as source,
open(output_path, "w", encoding="utf-8") as target:
for line in source:
clean_line = line.strip()
# 跳过空行
if not clean_line:
continue
# 跳过包含任意屏蔽词的行
if any(word in clean_line for word in blocked_words):
continue
target.write(clean_line + "n")
print(f"清洗完成,结果已写入:{output_path}")
这个版本会删除每行开头和结尾的空格。如果原文本中的缩进具有实际意义,例如代码或配置内容,就不应使用 strip() 作为最终写入内容,而应该只用它进行空行判断:
if not line.strip():
continue
clean_line = line.rstrip("rn")
target.write(clean_line + "n")
常见问题和处理方式
如果文件不存在,open() 会报错。可以在打开前检查路径:
from pathlib import Path
input_path = Path("input.txt")
if not input_path.exists():
print("找不到输入文件")
else:
with input_path.open("r", encoding="utf-8") as file:
for line in file:
print(line, end="")
如果输出文件已经存在,使用 "w" 会覆盖它。需要保留旧内容时,应改用 "a",但文本清洗通常需要重新生成完整结果,因此覆盖模式更符合预期。
还要注意读取和写入的编码应保持一致。比如读取时使用 UTF-8,写入时也使用 UTF-8:
with open("input.txt", "r", encoding="utf-8") as source,
open("output.txt", "w", encoding="utf-8") as target:
for line in source:
target.write(line)
对于普通清洗脚本,可以按照“明确编码、逐行读取、先判断空行、再执行筛选、最后写入”的顺序组织代码。这样既能减少乱码问题,也能避免不必要的内存占用,并且更容易在后续增加新的筛选条件。








