Мне нужно прочитать выбранные файлы, соответствующие имени файла, из удаленного zip-архива с помощью Python. Я не хочу сохранять полный zip-архив во временный файл (он не такой большой, поэтому я могу обрабатывать все, что есть в памяти).
Я уже написал код, и он работает, и я сам отвечаю на него, чтобы потом поискать. Но поскольку данные свидетельствуют о том, что я один из тупых участников Stackoverflow, я уверен, что есть возможности для улучшения.






Вот как я это сделал (захватил все файлы, заканчивающиеся на ".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
Почему вы не используете ZipFile(urllib2.urlopen(url))?
Я пробовал это, но не смог заставить его работать, потому что, хотя это был объект, подобный файлу, он не поддерживал конкретную функцию, в которой нуждался Zipfile. Вот почему я добавил его в буфер cStringIO.
Каталог для zip-файла хранится в конце, поэтому весь файл должен быть загружен перед извлечением, будь то в память или на диск.
Не так уж и сложно создать свой собственный файловый объект, чтобы обернуть URL-адрес, чтобы вам не нужно было загружать все это: stackoverflow.com/questions/7829311/…
Имейте в виду, что простая распаковка ZIP-файла может привести к уязвимость безопасности.
Спасибо, Марсель, за ваш вопрос и ответ (у меня была такая же проблема в другом контексте, и я столкнулся с той же проблемой с файловыми объектами, которые на самом деле не похожи на файлы)! Просто в качестве обновления: для Python 3.0 ваш код необходимо немного изменить:
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
Это сделает работу без загрузки всего zip-файла!
Вы хотите заменить первую строку на: import urllib2, zipfile.