Como faço para ler arquivos selecionados de um arquivo Zip remoto através de HTTP utilizando Python?
Pergunta
Eu preciso ler arquivos selecionados, correspondência no nome do arquivo, a partir de um arquivo zip remoto usando Python. Eu não quero para salvar o zip completo para um arquivo temporário (que não é tão grande, que eu possa lidar com tudo na memória).
Eu já escrevi o código e ele funciona, e eu estou respondendo isso mesmo que eu possa procurá-lo mais tarde. Mas desde que a evidência sugere que eu sou um dos participantes mais mudos sobre Stackoverflow, eu tenho certeza que há espaço para melhorias.
Solução
Aqui está como eu fiz isso (agarrando todos os arquivos que terminam em ".ranks"):
import urllib2, cStringIO, zipfile
try:
remotezip = urllib2.urlopen(url)
zipinmemory = cStringIO.StringIO(remotezip.read())
zip = zipfile.ZipFile(zipinmemory)
for fn in zip.namelist():
if fn.endswith(".ranks"):
ranks_data = zip.read(fn)
for line in ranks_data.split("\n"):
# do something with each line
except urllib2.HTTPError:
# handle exception
Outras dicas
Graças Marcel para a sua pergunta e resposta (Eu tive o mesmo problema em um contexto diferente e encontrou a mesma dificuldade com arquivo-como objetos não sendo realmente arquivo-like)! Assim como uma atualização: Para Python 3.0, o código precisa ser ligeiramente modificado:
import urllib.request, io, zipfile
try:
remotezip = urllib.request.urlopen(url)
zipinmemory = io.BytesIO(remotezip.read())
zip = zipfile.ZipFile(zipinmemory)
for fn in zip.namelist():
if fn.endswith(".ranks"):
ranks_data = zip.read(fn)
for line in ranks_data.split("\n"):
# do something with each line
except urllib.request.HTTPError:
# handle exception
Isto irá fazer o trabalho sem baixar todo o arquivo zip!
Tenha em mente que apenas descompactar um arquivo ZIP pode resultar em um vulnerabilidade de segurança.