Рекурсивно распаковать архивы, сохранить (имя файла, извлеченное содержимое) в словаре

Не могли бы вы помочь мне написать функцию, возвращающую:

dict("file1.txt": list(<contents of file1>),
     "file2.txt": list(<contents of file2>),
     "file3.txt": list(<contents of file3>),
     "file4.txt": list(<contents of file4>))

На входе:

    file.zip:
        outer\
        outer\inner1.zip:
                file1.txt
                file2.txt
        outer\inner2.zip:
                file3.txt
                file4.txt

Мои попытки (с исключениями ниже):

  • http://ideone.com/s1tyb

    WindowsError: [Ошибка 32] Процесс не может получить доступ к файлу, так как он используется другим процессом

  • http://ideone.com/Y2oTw

    "Файл не является zip-файлом"

  • http://ideone.com/0HoGa

    "Файл не является zip-файлом"

  • http://ideone.com/owmdK

    AttributeError: Экземпляр ZipFile не имеет атрибута "seek"


person user1438003    schedule 05.06.2012    source источник
comment
@MikePennington Я пытался сам написать и отладить код. См. 3 по-разному сформулированных ссылки на код в моем вопросе.   -  person user1438003    schedule 05.06.2012
comment
Спасибо @wroniasty, это не позволило мне добавить больше двух ссылок (в конце концов, это мой первый вопрос!)   -  person user1438003    schedule 05.06.2012


Ответы (2)


Наконец-то получилось... с небольшой помощью: Извлечение zip-файла в память?;

from zipfile import ZipFile, is_zipfile

def extract_zip(input_zip):
    input_zip=ZipFile(input_zip)
    return {name: input_zip.read(name) for name in input_zip.namelist()}

def extract_all(input_zip): 
    return {entry: extract_zip(entry) for entry in ZipFile(input_zip).namelist() if is_zipfile(entry)}
person user1438003    schedule 06.06.2012

Изменил ваш код (вы должны закрыть ZipFile перед его удалением + добавлено извлечение внутренних zip-файлов):

import os
import shutil
import tempfile
from zipfile import ZipFile

def unzip_recursively(parent_archive):
    parent_archive = ZipFile(parent_archive)
    result = {}
    tmpdir = tempfile.mkdtemp()
    try:
        parent_archive.extractall(path=tmpdir)
        namelist=parent_archive.namelist()
        for name in namelist[1:]:
            innerzippath = os.path.join(tmpdir, name)
            inner_zip = ZipFile(innerzippath)
            inner_extract_path = innerzippath+'.content'
            if not os.path.exists(inner_extract_path):
                os.makedirs(inner_extract_path)
            inner_zip.extractall(path=inner_extract_path)

            for inner_file_name in inner_zip.namelist():
                result[inner_file_name] = open(os.path.join(inner_extract_path, inner_file_name)).read()
            inner_zip.close()
    finally:
        shutil.rmtree(tmpdir)
    return result

if __name__ == '__main__':
    print unzip_recursively('file.zip')
person Arseniy    schedule 06.06.2012
comment
Спасибо, но этот код намного сложнее, чем мой... есть ли способ очистить почтовый индекс, добавив всего один больше функций для моего? - На самом деле я думаю, что сборщики мусора Python могут автоматически очищать память... поправьте меня, если я ошибаюсь. - person user1438003; 06.06.2012