2013-04-28 5 views
5

중첩 된 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 문의 nesting syntax 둥지 수준의 번호가있을 수 있기 때문이다.

을 첫 번째 파일이 즉시 종료되지 않으므로 예외가 발생하면 두 번째를 열 때이 개 파일을 열 수있는 프로그래밍 오류를 nested()입니다 사용 ... : 워드 프로세서가 바로 거기 말 때문에 나는 contextlib.nested을 사용할 수 없습니다 파일.

언어 구성을 사용하여이 작업을 수행 할 수있는 방법이 있습니까? 아니면 직접 열린 파일 개체 스택을 수동으로 관리해야합니까?

+2

3.3에서는 ['contextlib.ExitStack'] (HTTP를 사용할 수 있습니다. org/3/library/contextlib.html # contextlib.ExitStack). – delnan

+0

@delnan - 파이썬 3을 사용하지 못하게하는 ** 의존성이 하나 있습니다 :/ – detly

+0

@delnan 니스! 나는 이것이 python3.3에 추가 된 것을 몰랐다. 정말로 깨끗한 해결책 인 것 같습니다. – Bakuriu

답변

4

이 경우 재귀를 사용할 수 있습니다. 그것은 (파이썬에서 특별한 치료가 아직 존재하지 않는 경우는 물론)의 경우 가장 자연스러운 것으로 느낀다 : //docs.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 
+1

이것은 유일한 해결책으로 보입니다. '__enter__'과'__exit__' 메쏘드를 수동으로 호출하는 커스텀 콘텍스트 매니저를 작성할 수는 있지만 예외를 다루는 것이 정말 어려워진다. – Bakuriu