透明打开压缩文件
项目描述
xopen
此Python模块提供了一个名为 xopen 的函数,它类似于Python内置的 open 函数,但还可以透明地处理压缩文件。xopen 选择读取或写入压缩文件的最有效方法。
支持的压缩格式包括
gzip (.gz)
bzip2 (.bz2)
xz (.xz)
Zstandard (.zst)(可选)
xopen 与Python 3.8及更高版本兼容。
示例用法
打开文件以读取
from xopen import xopen with xopen("file.txt.gz") as f: content = f.read()
以二进制模式写入文件,设置压缩级别,并避免使用外部进程
from xopen import xopen with xopen("file.txt.xz", mode="wb", threads=0, compresslevel=3) as f: f.write(b"Hello")
xopen 函数
xopen 模块提供了一个名为 xopen 的单一函数,其签名如下
xopen( filename: str | bytes | os.PathLike, mode: Literal["r", "w", "a", "rt", "rb", "wt", "wb", "at", "ab"] = "r", compresslevel: Optional[int] = None, threads: Optional[int] = None, *, encoding: str = "utf-8", errors: Optional[str] = None, newline: Optional[str] = None, format: Optional[str] = None, ) -> IO
该函数使用适合检测到的文件格式的函数打开文件,并返回一个类似打开文件的对象。
在编写时,文件格式是根据文件扩展名选择的:.gz、.bz2、.xz、.zst。这可以通过format来覆盖。如果扩展名不被识别,则不使用压缩。
在读取时,如果文件名扩展名可用,格式从扩展名中检测。在读取时没有文件名扩展名,格式从文件签名(https://zh.wikipedia.org/wiki/文件格式#魔数)中检测。
参数
filename(str、bytes或os.PathLike):要打开的文件的名称。
如果设置为"-",则返回标准输出(在模式"w"中)或标准输入(在模式"r"中)。
mode、encoding、errors、newline:这些参数与Python内置的open函数的意义相同,只是默认编码总是UTF-8而不是首选的区域设置编码。encoding、errors和newline仅在以文本模式打开文件时使用。
compresslevel:写入gzip、xz和Zstandard文件的压缩级别。如果设置为None,则使用默认值,取决于格式:gzip:1,xz:6,Zstandard:3。
此参数对于其他压缩格式将被忽略。
format:覆盖自动检测的输入或输出格式。可能的值是:"gz"、"xz"、"bz2"、"zst"。
threads:设置用于压缩或解压缩的额外线程数。如果后端不支持线程,则可能被忽略。
如果threads为None(默认值),则使用尽可能多的CPU核心,但不超过四个。
xopen尝试将(解)压缩卸载到其他线程,以释放主Python线程供应用程序使用。这可以通过使用子进程到外部应用程序或使用支持线程的库来完成。
将线程数设置为0,以强制xopen只使用主Python线程。
后端
gzip文件的打开委托给以下程序或库之一
python-isal。支持多线程和压缩级别高达3。
pigz(gzip的并行版本)
对于xz文件,使用到xz程序的管道,因为它内置了多线程压缩支持。
对于bz2文件,使用pbzip2(并行bzip2)。
如果以上方法都不可用,xopen将回退到Python内置函数(gzip.open、lzma.open、bz2.open)。
可重现性
xopen以可重现的方式写入gzip文件。
通常,gzip文件包含文件头中的时间戳,这意味着在不同时间压缩相同的数据将产生不同的输出文件。xopen禁用了所有支持的gzip压缩后端。例如,当使用外部进程时,它设置命令行选项--no-name(等同于-n)。
请注意,不同的gzip压缩后端通常不会产生相同的输出,因此当执行环境从一次xopen()调用更改为下一次时,可重现性可能不再保证。这包括CPU架构,因为igzip会根据它调整其算法。
bzip2和xz压缩方法不将时间戳存储在文件头中,因此它们的输出也可以重现。
可选的Zstandard支持
对于读取和写入Zstandard (.zst)文件,需要安装zstd命令行程序或Python的zstandard包。
如果xopen()的threads参数为None(默认)或任何大于0的值,xopen将使用外部zstd进程。
如果上述操作失败(因为没有可用的zstd程序)或如果threads为0,则使用zstandard包。
为确保您获得正确的zstandard版本,您可以指定xopen的zstd扩展,即使用pip install xopen[zstd]进行安装。
更新日志
v2.0.2 (2024-06-12)
#161: 修复了读取大型压缩文件时外部程序触发的错误。
v2.0.1 (2024-03-28)
#158: 修复了从stdin和其他管道读取时丢弃输入的第一个字节的问题。
#156: 现在可以打开使用--long=31压缩的Zstd文件而不会引发错误。
v2.0.0 (2024-03-26)
#154: 使gzip级别的支持更加一致。支持0-9级别。当存在pigz后端时才可用的11级不再受支持。当使用作为后端的gzip应用程序后端时,不进行压缩的gzip格式0级会导致崩溃,因为该后端没有-0标志。xopen()现在在这种情况下将取决于其他后端。
#152: xopen()现在接受类似文件的对象作为其文件名参数。
#146, #147, #148: 对代码大小和可读性进行了各种重构。
PipedCompressionReader/Writer现在合并为_PipedCompressionProgram类。
_PipedCompressionProgram是二进制文件。对于文本读取和写入,在xopen()函数中使用io.TextIOWrapper进行包装。
已删除从PipedCompressionReader/Writer派生的类。
#148: xopen的与管道读取和写入相关的类、变量和函数全部通过前缀下划线变为私有。这些不是API的一部分,并且可能在版本之间发生变化。
v1.9.0 (2024-01-31)
#142: 现在python-isal压缩后端仅用于1和2压缩级别。与其他后端不同,python-isal的0级在gzip格式中提供了压缩数据而不是未压缩数据。python-isal的3级没有比2级更好的压缩效果。
#140: PipedCompressionReader/Writer现在从io.IOBase抽象类派生。
#138: 当调用函数没有提供值时,gzip的默认压缩级别现在是1。默认值以前由后端确定。
#135: xopen现在在适用的情况下使用zlib-ng。
编号133:已不再使用igzip作为(解)压缩后端,因为在所有用例中,python-isal的线程模式都是更好的选择。
版本1.8.0(2023-11-03)
编号131:xopen现在在适用情况下会委托给isal.igzip_threaded模块,而不是将数据通过管道传输到外部程序。这使得使用线程读写gzip文件更加高效。
不再支持Python 3.7,并添加了对Python 3.12的支持。
版本1.7.0(2022-11-03)
编号91:增加了对Zstandard(.zst)文件的可选支持。这需要安装Python的zstandard包或者确保zstd命令行程序可用。
版本1.6.0(2022-08-10)
编号94:在写入gzip文件时,省略原始文件的日期和时间戳(等同于在命令行中使用gzip --no-name(或-n))。这允许以可重复的方式写入文件。
版本1.5.0(2022-03-23)
编号100:不再支持Python 3.6。
编号101:添加了对从外部xz进程进行管道传输的支持。由@fanninpm贡献。
编号102:支持设置xz压缩级别。由@tsibley贡献。
版本1.4.0(2022-01-14)
为PipedCompressionReader类添加了seek()和tell()方法(以支持Windows兼容性)
版本1.3.0(2022-01-10)
xopen现在在Windows上可用(除了Linux和macOS)。
为了与内置的open()函数有更好的兼容性,xopen()增加了encoding、errors和newlines参数,这些参数的含义与open()中相同。然而,与内置的open()不同,编码默认为UTF-8。
增加了一个format参数,允许强制指定压缩文件格式。
版本1.2.0(2021-09-21)
pbzip2现在在threads大于零时用于打开.bz2文件(由@DriesSchaumont贡献)。
版本1.1.0(2021-01-20)
不再支持Python 3.5。
在Linux系统上,现在将python-isal添加为必需依赖项。当不使用外部进程时,这将显著加快gzip文件的读取速度。
版本1.0.0(2020-11-05)
如果已安装,则程序igzip(Intel ISA-L的一部分)现在用于在压缩级别1-3时读取和写入gzip压缩文件,这可以显著提高速度。
版本0.9.0(2020-04-02)
编号80:当要打开读取的文件的文件名扩展名不可用时,将检查内容(如果可能)并用于确定适用的压缩格式(由@bvaisvil贡献)。
本发行版不再支持Python 2.7和3.4。现在需要Python 3.5或更高版本。
版本0.8.4(2019-10-24)
在读取gzip文件时,强制pigz只使用单个进程。实际上,pigz在解压缩时无法使用多个核心。默认情况下,它会使用额外的I/O进程,这略微减少了wall-clock时间,但增加了CPU时间。使用pigz的单核解压缩速度仍然比常规gzip快约两倍。
允许threads=0来指定不应使用外部pigz/gzip进程(此时将使用常规的gzip.open())。
版本0.8.3(2019-10-18)
编号20:在读取gzip文件时,默认让pigz最多使用四个线程。此限制以前仅适用于写入文件。由@bernt-matthias贡献。
支持 Python 3.8
v0.8.0 (2019-08-14)
#14: 优化迭代压缩文件时的速度。
v0.6.0 (2019-05-23)
在读取压缩文件时,xopen现在将使用一个pigz子进程。这比使用gzip.open更快。
将在未来的某个版本中放弃Python 2支持。
v0.5.0 (2019-01-30)
默认情况下,现在只允许pigz最多使用四个线程。这有望减少一些用户在同时打开许多文件时遇到的多线程问题。
xopen现在接受pathlib.Path对象。
v0.4.0 (2019-01-07)
放弃Python 3.3支持
添加一个threads参数(传递给pigz)
v0.3.2 (2017-11-22)
#6: 通过使用外部bz2file库使多块bz2在Python 2上工作。
v0.3.1 (2017-11-22)
放弃Python 2.6支持
#5: 修复PipedGzipReader.read()不返回任何内容的问题
v0.3.0 (2017-11-15)
添加gzip压缩参数
v0.2.1 (2017-05-31)
#3: 尽可能允许向bz2和lzma文件追加内容
v0.1.1 (2016-12-02)
修复一个死锁问题
v0.1.0 (2016-09-09)
初始发布
致谢
xopen这个名称来源于BWA中相同名称的C函数,该函数包含在utils.h文件中。
一些想法来自canopener项目。如果您也想打开S3文件,您可能需要使用该模块。
@kyleabeauchamp在创建此存储库之前贡献了对文件追加的支持。
维护者
Marcel Martin
Ruben Vorderman
另请参阅完整贡献者列表。
链接
项目详情
下载文件
下载适用于您的平台的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。