我已经阅读了如何将字符串写入压缩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中使用管道操作符来压缩任何类型的输出(这也使其端点并行,但这在这里不是很重要)。
我的问题是:像compressed_stream_adapter()
存在于python吗?有没有别的方法可以让不需要更改现有代码?
注意,我已经知道我可以做:out = io.StringIO ()
和以后:f.write ( out.getvalue ().encode () )
。但是,当我必须动态地将大量数据转储到文件中时(这确实是我想要压缩它们的原因),这就不太好了。
回答自己:我想没有现成的方法可以做到这一点。
因此,我遵循了Dan Mašek的注释并实现了一个小包装器,它依赖于print()期望对象具有write方法的事实: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 ()