@@ -60,7 +60,7 @@ def open(filename, mode="rb", compresslevel=igzip._COMPRESS_LEVEL_TRADEOFF,
60
60
gzip_file = io .BufferedReader (
61
61
_ThreadedGzipReader (filename , block_size = block_size ))
62
62
else :
63
- gzip_file = io . BufferedWriter (
63
+ gzip_file = FlushableBufferedWriter (
64
64
_ThreadedGzipWriter (
65
65
filename ,
66
66
mode .replace ("t" , "b" ),
@@ -167,6 +167,12 @@ def closed(self) -> bool:
167
167
return self ._closed
168
168
169
169
170
+ class FlushableBufferedWriter (io .BufferedWriter ):
171
+ def flush (self ):
172
+ super ().flush ()
173
+ self .raw .flush ()
174
+
175
+
170
176
class _ThreadedGzipWriter (io .RawIOBase ):
171
177
"""
172
178
Write a gzip file using multiple threads.
@@ -310,30 +316,35 @@ def write(self, b) -> int:
310
316
self .input_queues [worker_index ].put ((data , zdict ))
311
317
return len (data )
312
318
313
- def flush (self ):
319
+ def _end_gzip_stream (self ):
314
320
self ._check_closed ()
315
321
# Wait for all data to be compressed
316
322
for in_q in self .input_queues :
317
323
in_q .join ()
318
324
# Wait for all data to be written
319
325
for out_q in self .output_queues :
320
326
out_q .join ()
327
+ # Write an empty deflate block with a lost block marker.
328
+ self .raw .write (isal_zlib .compress (b"" , wbits = - 15 ))
329
+ trailer = struct .pack ("<II" , self ._crc , self ._size & 0xFFFFFFFF )
330
+ self .raw .write (trailer )
331
+ self ._crc = 0
332
+ self ._size = 0
321
333
self .raw .flush ()
322
334
335
+ def flush (self ):
336
+ self ._end_gzip_stream ()
337
+ self ._write_gzip_header ()
338
+
323
339
def close (self ) -> None :
324
340
if self ._closed :
325
341
return
326
- self .flush ()
342
+ self ._end_gzip_stream ()
327
343
self .stop ()
328
344
if self .exception :
329
345
self .raw .close ()
330
346
self ._closed = True
331
347
raise self .exception
332
- # Write an empty deflate block with a lost block marker.
333
- self .raw .write (isal_zlib .compress (b"" , wbits = - 15 ))
334
- trailer = struct .pack ("<II" , self ._crc , self ._size & 0xFFFFFFFF )
335
- self .raw .write (trailer )
336
- self .raw .flush ()
337
348
if self .closefd :
338
349
self .raw .close ()
339
350
self ._closed = True
@@ -366,41 +377,31 @@ def _compress(self, index: int):
366
377
def _write (self ):
367
378
index = 0
368
379
output_queues = self .output_queues
369
- fp = self .raw
370
- total_crc = 0
371
- size = 0
372
380
while True :
373
381
out_index = index % self .threads
374
382
output_queue = output_queues [out_index ]
375
383
try :
376
384
compressed , crc , data_length = output_queue .get (timeout = 0.05 )
377
385
except queue .Empty :
378
386
if not (self .running and self ._calling_thread .is_alive ()):
379
- self ._crc = total_crc
380
- self ._size = size
381
387
return
382
388
continue
383
- total_crc = isal_zlib .crc32_combine (total_crc , crc , data_length )
384
- size += data_length
385
- fp .write (compressed )
389
+ self . _crc = isal_zlib .crc32_combine (self . _crc , crc , data_length )
390
+ self . _size += data_length
391
+ self . raw .write (compressed )
386
392
output_queue .task_done ()
387
393
index += 1
388
394
389
395
def _compress_and_write (self ):
390
396
if not self .threads == 1 :
391
397
raise SystemError ("Compress_and_write is for one thread only" )
392
- fp = self .raw
393
- total_crc = 0
394
- size = 0
395
398
in_queue = self .input_queues [0 ]
396
399
compressor = self .compressors [0 ]
397
400
while True :
398
401
try :
399
402
data , zdict = in_queue .get (timeout = 0.05 )
400
403
except queue .Empty :
401
404
if not (self .running and self ._calling_thread .is_alive ()):
402
- self ._crc = total_crc
403
- self ._size = size
404
405
return
405
406
continue
406
407
try :
@@ -410,9 +411,9 @@ def _compress_and_write(self):
410
411
self ._set_error_and_empty_queue (e , in_queue )
411
412
return
412
413
data_length = len (data )
413
- total_crc = isal_zlib .crc32_combine (total_crc , crc , data_length )
414
- size += data_length
415
- fp .write (compressed )
414
+ self . _crc = isal_zlib .crc32_combine (self . _crc , crc , data_length )
415
+ self . _size += data_length
416
+ self . raw .write (compressed )
416
417
in_queue .task_done ()
417
418
418
419
def _set_error_and_empty_queue (self , error , q ):
0 commit comments