6

ネストされた tar アーカイブを表す任意の数のパスを取得し、最も内側のアーカイブに対して操作を実行したいと考えています。問題は、ネスティングが任意になる可能性があるため、必要なコンテキスト マネージャーの数も任意になることです。

たとえば、次のようにします。

ARCHIVE_PATH = "path/to/archive.tar"

INNER_PATHS = (
    "nested/within/archive/one.tar",
    "nested/within/archive/two.tar",
    # Arbitary number of these
)

def list_inner_contents(archive_path, inner_paths):
    with TarFile(archive_path) as tf1:
        with TarFile(fileobj=tf1.extractfile(inner_paths[0])) as tf2:
            with TarFile(fileobj=tf2.extractfile(inner_paths[1])) as tf3:
                # ...arbitary level of these!
                return tfX.getnames()

contents = list_inner_contents(ARCHIVE_PATH, INNER_PATHS))

ネストするレベルはいくつでもある可能性があるため、withステートメントのネスト構文は使用できません。contextlib.nestedドキュメントに次のように記載されているため、使用できません。

... nested()2 番目のファイルを開くときに例外がスローされると、最初のファイルがすぐに閉じられないため、2 つのファイルを開くために使用することはプログラミング エラーです。

これを行うために言語構造を使用する方法はありますか?それとも、開いているファイル オブジェクトの独自のスタックを手動で管理する必要がありますか?

4

1 に答える 1

5

この場合、再帰を使用できます。この場合、これが最も自然に感じられます (もちろん、まだ Python で特別な処理が行われていない場合):

ARCHIVE_PATH = "path/to/archive.tar"

INNER_PATHS = [
    "nested/within/archive/one.tar",
    "nested/within/archive/two.tar",
    # Arbitary number of these
]

def list_inner_contents(archive_path, inner_paths):
    def rec(tf, rest_paths):
        if not rest_paths:
            return tf.getnames()

        with TarFile(fileobj=tf.extractfile(rest_paths[0])) as tf2:
            return rec(tf2, rest_paths[1:])

    with TarFile(archive_path) as tf:
        try:
            return rec(tf, inner_paths)
        except RuntimeError:
            # We come here in case the inner_paths list is too long
            # and we go too deeply in the recursion
            return None
于 2013-04-28T05:20:30.320 に答える