2016-06-21 5 views
0

Ich möchte eine große Protokolldatei mit asyncio über das Netzwerk streamen. Ich erhalte die Daten aus der Datenbank, formatiere sie, komprimiere sie mit pythons zlib und streame sie über das Netzwerk.Wie streame man ein gzip, das in Python on the fly gebaut wurde?

Hier ist im Grunde der Code, den ich verwenden:

@asyncio.coroutine 
def logs(requests): 
    # ... 

    yield from resp.prepare(request) 

    # gzip magic number and compression format 
    resp.write(b'\x1f\x8b\x08\x00\x00\x00\x00\x00') 
    compressor = compressobj() 
    for row in rows: 
     ip, uid, date, url, answer, volume = row 
     NCSA_ROW = '{} {} - [{}] "GET {} HTTP/1.0" {} {}\n' 
     row = NCSA_ROW.format(ip, uid, date, url, answer, volume) 
     row = row.encode('utf-8') 
     data = compressor.compress(row) 
     resp.write(data) 
    resp.write(compressor.flush()) 
    return resp 

Die Datei, die ich abrufen kann nicht mit gunzip geöffnet werden und die folgenden Fehler zcat zu erhöhen:

gzip: out.gz: unexpected end of file 

Antwort

1

Ihr gzip-Header ist falsch (8 Bytes statt 10), und Sie folgen ihm mit einem zlib-Stream, der einen anderen Header und einen anderen Trailer verwendet. Selbst wenn du einen korrekten gzip-Header gehabt hättest, und wenn du einen rohen Deflate-Stream anstelle eines gzip-Streams hättest, hättest du immer noch keinen gzip-Trailer geschrieben.

Um dies richtig zu machen, versuchen Sie nicht, Ihren eigenen gzip-Header zu schreiben. Fordern Sie stattdessen an, dass zlib einen vollständigen gzip-Stream schreibt, der den richtigen Header, die komprimierten Daten und den Trailer schreibt. Sie können dies tun, indem Sie einen wbits Wert von 31 bis compressobj() angeben.