2013-03-12 9 views
24

Vorrei scaricare un file usando urllib e decomprimere il file in memoria prima di salvare.Scaricare e decomprimere il file gzippato in memoria?

Questo è ciò che ho in questo momento:

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()) 

Questo finisce per la scrittura di file vuoti. Come posso ottenere ciò che sto cercando?

Risposta Aggiornato:

#! /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

cosa c'è di sbagliato con decompressione su disco? – MattDMo

+2

Sto decomprimendo su disco, semplicemente non lasciando mai che i byte compressi tocchino il disco. – OregonTrail

+0

il file '' compressedFile' 'non ci mette mai dentro? – MattDMo

risposta

35

È necessario cercare l'inizio di compressedFile dopo la scrittura ad esso, ma prima di passarlo a gzip.GzipFile(). Altrimenti verrà letto dalla fine del modulo gzip e verrà visualizzato come un file vuoto. Vedi sotto:

#! /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

Si scopre che avrei potuto approfittare di '__init__' di StringIO, vedere la domanda aggiornata. – OregonTrail

+0

Sì. Funziona ancora meglio. :) Lascerò la mia risposta inedita come hai già aggiunto la risposta aggiornata. Grazie. – crayzeewulf

+0

@OregonTrail: oppure è possibile ritagliare il middleman e [passare 'response' direttamente] (http://stackoverflow.com/a/26435241/4279). btw, non mettere * le risposte * nella domanda; [sei incoraggiato a pubblicare la tua risposta] (http://stackoverflow.com/help/self-answer). – jfs

9

Per coloro che utilizzano Python 3, la risposta equivalente è:

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

non funzionerà: stai provando a scrivere byte in un file di testo; utilizzare invece la modalità binaria. Prova: 'copyfileobj (GzipFile (fileobj = response), open (outfile_path, 'wb'))' – jfs

6

Se si dispone di Python 3.2 o superiore, la vita sarebbe molto più facile:

#!/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())) 

Per coloro che sono interessati alla storia, vedere https://bugs.python.org/issue3488 e https://hg.python.org/cpython/rev/3fa0a9553402.

-2

Un codice di linea per stampare il contenuto del file decompresso:

print gzip.GzipFile(fileobj=StringIO.StringIO(urllib2.urlopen(DOWNLOAD_LINK).read()), mode='rb').read() 
Problemi correlati