12

Python でネストされた zip ファイルを解凍する方法を探しています。たとえば、次の構造を考えてみましょう (わかりやすくするために架空の名前を使用しています)。

  • フォルダ
    • ZipfileA.zip
      • ZipfileA1.zip
      • ZipfileA2.zip
    • ZipfileB.zip
      • ZipfileB1.zip
      • ZipfileB2.zip

...等。2 番目の zip 内にあるテキスト ファイルにアクセスしようとしています。せん断数がコンピューターをクラッシュさせるため、すべてを抽出したくはありません (最初のレイヤーには数百の zip があり、2 番目のレイヤーには (zip ごとに) ほぼ 10,000 の zip があります)。

「zipfile」モジュールをいじってみました - 第 1 レベルの zipfile を開くことができました。例えば:

zipfile_obj = zipfile.ZipFile("/Folder/ZipfileA.zip")
next_layer_zip = zipfile_obj.open("ZipfileA1.zip")

ただし、これは「ZipExtFile」インスタンス (ファイルまたは zipfile インスタンスではありません) を返します。この特定のデータ型を開くことはできません。私はこれを行うことができないこと:

data = next_layer_zip.open(data.txt)

ただし、このzipファイルは次の方法で「読み取る」ことができます。

next_layer_zip.read()

しかし、これはまったく役に立ちません!(つまり、圧縮データ/goobledigook のみを読み取ることができます)。

( ZipFile.extractを使用せずに)これをどのように行うかについて誰かアイデアがありますか??

私はこれに出くわしましたhttp://pypi.python.org/pypi/zip_open/ -これはまさに私が望むことをしているように見えますが、私にとってはうまくいかないようです。(そのモジュールを使用して、処理しようとしているファイルに対して「[Errno 2] No such file or directory:」を取得し続けます)。

どんなアイデアでも大歓迎です!! 前もって感謝します

4

7 に答える 7

9

ZipFileにはファイルのようなオブジェクトが必要なので、StringIOを使用して、ネストされたzipから読み取ったデータをそのようなオブジェクトに変換できます。注意点は、完全な(まだ圧縮された)内部zipをメモリにロードすることです。

with zipfile.ZipFile('foo.zip') as z:
    with z.open('nested.zip') as z2:
        z2_filedata = cStringIO.StringIO(z2.read())
        with zipfile.ZipFile(z2_filedata) as nested_zip:
            print nested_zip.open('data.txt').read()
于 2013-02-13T21:33:36.417 に答える
8

残念ながら、zip ファイルの解凍にはアーカイブへのランダム アクセスが必要であり、ZipFileメソッド (DEFLATE アルゴリズム自体は言うまでもありません) はストリームのみを提供します。したがって、ネストされた zip ファイルを解凍せずに解凍することはできません。

于 2012-08-13T08:24:02.390 に答える
6

これが私が思いついた機能です。

def extract_nested_zipfile(path, parent_zip=None):
    """Returns a ZipFile specified by path, even if the path contains
    intermediary ZipFiles.  For example, /root/gparent.zip/parent.zip/child.zip
    will return a ZipFile that represents child.zip
    """

    def extract_inner_zipfile(parent_zip, child_zip_path):
        """Returns a ZipFile specified by child_zip_path that exists inside
        parent_zip.
        """
        memory_zip = StringIO()
        memory_zip.write(parent_zip.open(child_zip_path).read())
        return zipfile.ZipFile(memory_zip)

    if ('.zip' + os.sep) in path:
        (parent_zip_path, child_zip_path) = os.path.relpath(path).split(
            '.zip' + os.sep, 1)
        parent_zip_path += '.zip'

        if not parent_zip:
            # This is the top-level, so read from disk
            parent_zip = zipfile.ZipFile(parent_zip_path)
        else:
            # We're already in a zip, so pull it out and recurse
            parent_zip = extract_inner_zipfile(parent_zip, parent_zip_path)

        return extract_nested_zipfile(child_zip_path, parent_zip)
    else:
        if parent_zip:
            return extract_inner_zipfile(parent_zip, path)
        else:
            # If there is no nesting, it's easy!
            return zipfile.ZipFile(path)

これが私がそれをテストした方法です:

echo hello world > hi.txt
zip wrap1.zip hi.txt
zip wrap2.zip wrap1.zip
zip wrap3.zip wrap2.zip

print extract_nested_zipfile('/Users/mattfaus/dev/dev-git/wrap1.zip').open('hi.txt').read()
print extract_nested_zipfile('/Users/mattfaus/dev/dev-git/wrap2.zip/wrap1.zip').open('hi.txt').read()
print extract_nested_zipfile('/Users/mattfaus/dev/dev-git/wrap3.zip/wrap2.zip/wrap1.zip').open('hi.txt').read()
于 2013-07-01T23:20:14.577 に答える