2013-03-12 13 views
24

Chciałbym pobrać plik za pomocą urllib i rozpakować plik w pamięci przed zapisaniem.Pobierz i rozpakuj spakowany plik gzip w pamięci?

To co mam teraz:

response = urllib2.urlopen(baseURL + filename) 
compressedFile = StringIO.StringIO() 
compressedFile.write(response.read()) 
decompressedFile = gzip.GzipFile(fileobj=compressedFile, mode='rb') 
outfile = open(outFilePath, 'w') 
outfile.write(decompressedFile.read()) 

To kończy pisanie pustych plików. Jak mogę osiągnąć to, czego szukam?

Updated Odpowiedź:

#! /usr/bin/env python2 
import urllib2 
import StringIO 
import gzip 

baseURL = "https://www.kernel.org/pub/linux/docs/man-pages/" 
filename = "man-pages-3.34.tar.gz" 
outFilePath = filename[:-3] 

response = urllib2.urlopen(baseURL + filename) 
compressedFile = StringIO.StringIO(response.read()) 
decompressedFile = gzip.GzipFile(fileobj=compressedFile) 

with open(outFilePath, 'w') as outfile: 
    outfile.write(decompressedFile.read()) 
+0

Co jest złego w dekompresji na dysku? – MattDMo

+2

Dekompresuję się na dysk, po prostu nigdy nie pozwalając skompresowanym bajtom dotknąć dysku. – OregonTrail

+0

Czy "compressedFile" kiedykolwiek się w to wkłada? – MattDMo

Odpowiedz

35

Trzeba dążyć do początku compressedFile po napisaniu do niego, ale przed przekazaniem go do gzip.GzipFile(). W przeciwnym razie zostanie odczytany od końca przez moduł gzip i pojawi się jako pusty plik do niego. Patrz poniżej:

#! /usr/bin/env python 
import urllib2 
import StringIO 
import gzip 

baseURL = "https://www.kernel.org/pub/linux/docs/man-pages/" 
filename = "man-pages-3.34.tar.gz" 
outFilePath = "man-pages-3.34.tar" 

response = urllib2.urlopen(baseURL + filename) 
compressedFile = StringIO.StringIO() 
compressedFile.write(response.read()) 
# 
# Set the file's current position to the beginning 
# of the file so that gzip.GzipFile can read 
# its contents from the top. 
# 
compressedFile.seek(0) 

decompressedFile = gzip.GzipFile(fileobj=compressedFile, mode='rb') 

with open(outFilePath, 'w') as outfile: 
    outfile.write(decompressedFile.read()) 
+4

Okazało się, że mogłem skorzystać z '__init__' StringIO, zobacz zaktualizowane pytanie. – OregonTrail

+0

Tak. To działa jeszcze lepiej. :) Zostawię swoją odpowiedź jako nieedytowaną, ponieważ dodałeś już zaktualizowaną odpowiedź. Dzięki. – crayzeewulf

+0

@ OregonTrail: albo można wyciąć pośrednika i [podać 'odpowiedź' bezpośrednio] (http://stackoverflow.com/a/26435241/4279). btw, nie umieszczaj * odpowiedzi * na pytanie; [zachęcamy do opublikowania własnej odpowiedzi] (http://stackoverflow.com/help/self-answer). – jfs

9

dla osób korzystających Python 3, odpowiednik odpowiedź brzmi:

import urllib.request 
import io 
import gzip 

response = urllib.request.urlopen(FILE_URL) 
compressed_file = io.BytesIO(response.read()) 
decompressed_file = gzip.GzipFile(fileobj=compressed_file) 

with open(OUTFILE_PATH, 'wb') as outfile: 
    outfile.write(decompressed_file.read()) 
+0

to nie zadziała: próbujesz zapisać bajty do pliku tekstowego; zamiast tego użyj trybu binarnego. Spróbuj: 'copyfileobj (GzipFile (fileobj = response), open (outfile_path, 'wb'))' – jfs

6

Jeśli masz Python 3.2 lub nowszej, życie byłoby o wiele prostsze:

#!/usr/bin/env python3 
import gzip 
import urllib.request 

baseURL = "https://www.kernel.org/pub/linux/docs/man-pages/" 
filename = "man-pages-4.03.tar.gz" 
outFilePath = filename[:-3] 

response = urllib.request.urlopen(baseURL + filename) 
with open(outFilePath, 'wb') as outfile: 
    outfile.write(gzip.decompress(response.read())) 

Dla osoby zainteresowane historią, zobacz https://bugs.python.org/issue3488 i https://hg.python.org/cpython/rev/3fa0a9553402.

-2

Jedna linia kodu, aby wydrukować zawartość pliku rozpakowany:

print gzip.GzipFile(fileobj=StringIO.StringIO(urllib2.urlopen(DOWNLOAD_LINK).read()), mode='rb').read() 
Powiązane problemy