跳到正文
效率工具实用笔记关于本站
文件整理

如何读取gzip文本:用gzip.open指定文本模式

约 7 分钟阅读AI 辅助整理

用自建样例.gz演示gzip.open的rt模式与显式UTF-8编码,说明gzip与ZIP的区别,并给出读取失败时的排查方向。只读自建文件,不运行压缩包里的任何代码。

本文要点

  1. 要练习读取,先得有一个自己造的.gz文件

  2. 文件造好之后,读取时把mode写成'rt',就进入文本模式

  3. 读完之后,不要只看“没报错”就结束,应该把输出和你写入时的原文对一遍

如何读取gzip文本:用gzip.open指定文本模式的知识要点示意图
依据已审核正文摘取要点制作的示意图,非实物照片;请结合正文中的条件与范围阅读。要点摘自已审核正文;完整条件与说明见正文。查看高清图解 ↗
本文目录

先分清:gzip不是ZIP,读取方式也不同

如果你手里有一个.gz文件,想读出里面的文字,第一步不是打开它,而是确认它属于哪种压缩格式。

gzip模块的文档说明,GzipFile类读写的是gzip格式文件,会自动压缩或解压数据,让它看起来像一个普通文件对象。文档还专门指出:gzip和gunzip程序能解压的其他一些格式,比如compress和pack产生的文件,这个模块并不支持。

这一点决定了工具选择。gzip格式通常对应单个被压缩的数据流,文件名以.gz结尾;ZIP是另一种压缩格式,一个ZIP包里可以装多个成员,读取方式也不同。用gzip.open去读ZIP文件,或用zipfile去读.gz文件,都不对路。

本文只处理一件事:读取你自己创建的.gz文本样例,用gzip.open的文本模式把它当普通文本文件读出来。不涉及ZIP成员的读取,也不涉及压缩包里的任何代码。

动手前请把练习文件放在单独目录,例如exercise/,不要拿重要文件直接试。下面所有路径和内容都是自建练习示例。

一个边界:本文只读取你自己创建或可信来源的.gz文件。不要对来源不明的压缩包执行解压操作,更不要运行压缩包里附带的脚本或程序。

自建一个.gz样例:先写文本,再压缩成gzip

要练习读取,先得有一个自己造的.gz文件。做法是:先写一个普通文本文件,再用gzip.open以二进制写模式把它压成.gz。

按文档,gzip.open的mode参数默认是'rb',也就是二进制读。写文件时用'wb',写入的内容必须是bytes。下面这段只操作练习目录里的文件:

import gzip

text = "第一行:练习文本\n第二行:仅用于自建样例\n"
with gzip.open("exercise/sample.txt.gz", "wb") as f:
    f.write(text.encode("utf-8"))

这里有两个动作值得注意。第一,写入前用encode("utf-8")把字符串转成bytes,因为'wb'是二进制模式,不接受str。第二,with语句负责在结束时关闭文件,文档说明GzipFile支持with语句。

注意:这段代码只创建练习文件,不读取、不修改系统里其他任何文件。

用rt模式读取:为什么必须显式写UTF-8

文件造好之后,读取时把mode写成'rt',就进入文本模式。

文档对gzip.open的说明是:它可以在二进制或文本模式下打开gzip压缩文件,返回一个文件对象;mode可以是'rt'、'at'、'wt'、'xt'这些文本模式。文本模式下会创建一个GzipFile对象,并用指定的encoding、错误处理方式和换行规则把它包进一个io.TextIOWrapper实例。

这句话解释了为什么文本模式能直接读出字符串:底层还是GzipFile在解压,外面套了一层文本包装器负责解码。

读取示例如下:

import gzip

with gzip.open("exercise/sample.txt.gz", "rt", encoding="utf-8") as f:
    content = f.read()

print(content)

关键点是encoding="utf-8"要显式写出来。文档说明encoding参数用于文本模式;如果不指定,解码就依赖运行环境的默认编码,同一个文件在不同机器上可能读出不同结果,甚至报错。显式写UTF-8,等于把“这个文件按UTF-8解码”这件事固定下来,和你写入时用的编码对应。

另一个容易踩的坑:文档明确说,二进制模式下encoding、errors、newline这三个参数不能提供。也就是说,写'rb'时不能顺手加encoding,那会直接报错。要指定编码,mode就必须是文本模式。

读出来的结果怎么核对:对照输入与输出

读完之后,不要只看“没报错”就结束,应该把输出和你写入时的原文对一遍。

核对方法很简单:你写入的是两行中文,读出来应该也是同样的两行,换行位置一致,没有多余空行,没有乱码方块或问号。可以按下面几点逐项看:

1. 行数对不对。写入两行,读出也应是两行。

2. 文字有没有变形。中文应正常显示,不应出现乱码。

3. 换行有没有多出来。如果发现每行之间多了一个空行,先检查是不是换行处理的问题,而不是文件坏了。

一个提醒:核对时把读出的内容和写入时的原文放在一起看,这是判断读取是否正确的直接依据。不要凭“看起来差不多”就认定读对了。

读取失败时先查哪几类原因

如果读取时报错,按下面顺序排查,能覆盖大多数情况。

第一类,文件不存在。路径写错、目录不对,都会导致找不到文件。先确认练习目录里确实有exercise/sample.txt.gz这个文件。

第二类,文件不是gzip格式。文档说明,gzip.BadGzipFile是为无效gzip文件抛出的异常,它继承自OSError;文档还补充,无效gzip文件也可能抛出EOFError和zlib.error。所以如果你拿一个ZIP文件或普通文本文件去喂gzip.open,可能看到这几类异常。这时候要回到第一步:确认文件到底是不是gzip格式。

第三类,编码不匹配。文件本身不是UTF-8,却按UTF-8解码,会报解码错误。排查方向是确认写入时用的编码,让读取编码和它一致。

第四类,模式参数冲突。前面提过,二进制模式下不能传encoding。如果你写的是'rb'又加了encoding,会直接报错,把mode改成'rt'即可。

排查时一次只改一个地方,改完重新读,这样能确定到底是哪一项导致的。

使用限制:只读自建文件,不运行包内代码

最后说明本文的适用范围和几条限制。

本文只读取你自己创建的.gz文本样例,用gzip.open的文本模式配合显式UTF-8编码。它不涉及ZIP压缩包成员的读取,不涉及压缩级别调优,也不比较不同压缩方法的性能。

几条操作边界:

1. 只处理自建或可信来源的.gz文件。来源不明的压缩包不要解压。

2. 不运行压缩包里的任何脚本或程序。压缩包可能包含可执行内容,读取文本和运行代码是两件事。

3. 练习时把文件放在单独目录,例如exercise/,不要拿重要文件直接试。

4. 本文示例只做读取,不修改、不删除任何文件。

关于版本:文档说明gzip.open对文本模式及encoding、errors、newline参数的支持是Python 3.3加入的,'x'、'xb'、'xt'模式是3.4加入的,接受path-like对象是3.6加入的。如果你用的版本更早,文本模式可能不可用。

观看知识要点视频 18 秒

18秒无旁白要点导览,文字来自已审核正文;完整步骤、条件及参考资料见下方。

参考资料

以下原始资料提供本文依据;请结合日期、适用条件和产品说明查阅。

请结合原始资料的适用条件阅读。

返回文件整理 →