将 python print() 与 bzip2/gzip2/etc 流一起使用

Using python print() with a bzip2/gzip2/etc stream

我已阅读有关如何将字符串写入压缩 python 文件的文档:

with bz2.open ( "/tmp/test.bz2", "w" ) as f:
  f.write ( b"Hello" )

我遇到的问题是我的函数接受一个传递给 print() 函数的文件参数,即:

def produce_out ( out = sys.stdout ):
  # many print ( file = out )
  # invocations of other functions accepting out

显然,同时打印和压缩我的输出的最干净、最模块化的方法是将上面的两个链接起来,即:

with bz2.open ( "/tmp/test.bz2", "w" ) as f:
  out = compressed_stream_adapter ( f )
  produce_out ( out )

其中 compressed_stream_adapter() 生成一些与 print() 接受的 file 参数兼容的对象,它会自动将接收到的字符串转发到压缩流。这就是压缩在 Java 中的工作方式,或者您可以如何在 Linux shell 中使用管道运算符来压缩任何类型的输出(这也并行化了它的端点,但这在这里不是很重要)。

我的问题是:python 中是否存在类似 compressed_stream_adapter() 的东西?是否有其他方法可以做到这一点 不需要 更改现有代码?

请注意,我已经知道我可以做到:out = io.StringIO () 及以后: f.write ( out.getvalue ().encode () )。但是,当我必须将大量数据动态转储到文件时,这并不好(这确实是我要压缩它们的原因)。

回答我自己:我想没有任何现成的方法可以做到这一点。

所以,我遵循了 Dan Mašek comments and implemented a little wrapper,它依赖于 print() 需要一个具有写入方法的对象这一事实:

class BinaryWriter:
    def __init__ ( self, bin_out, encoding = "utf-8", errors = 'strict' ):
        self.bin_out = bin_out
        self.encoding = encoding
        self.errors = errors
        
    def write ( self, s: str ):
        self.bin_out.write ( s.encode ( self.encoding, self.errors ) )

    def close ( self ):
        self.bin_out.close ()

用法:

with bz2.open ( file_path, "w" ) as bout
    out = BinaryWriter ( bout )
    print ( "Hello, world", file = out )
    my_output ( out ) # Uses print( ..., file = out )

如果压缩是可选的:

out = open ( file_path, mode = "w" ) if not file_path.endswith ( ".bz2" ) \
            else BinaryWriter ( bz2.open ( file_path, "w" ) )
try:
    my_output ( out )
finally:
    out.close ()