2014-12-02 5 views
0

하위 디렉토리 방문을 제어하는 ​​컨텍스트 관리자를 사용하려고하는데,이를 생성기 표현식과 결합하는 것이 매우 우아하지만 작동하지 않는 것처럼 보입니다. 이 두 가지를 함께 사용할 수 있도록이 문제를 해결할 수있는 방법이 있습니까?파이썬 컨텍스트 관리자를 생성자와 함께 사용할 수 있습니까?

import os, sys 
from contextlib import contextmanager 
from glob import glob 

@contextmanager 
def visitDir(d): 
    os.chdir(d) 
    yield d 
    os.chdir("..") 

paths = [os.path.join('.', p[0:-1]) for p in glob('*/')] 

def clean(): 
    for p in (visitDir(p) for p in paths): # This is the magic line 
     print p 
     print os.getcwd() 

clean() # Context manager apparently expires within the generator expression 
+0

나는 * 스트림 *을 * 생성기 표현식 *으로 대체했습니다. * 스트림 *은 이에 적용되는 개념이 아닙니다. –

+0

생성기 표현식이 스트림을 생성하지 않습니까? 평가는 목록 표현식과 같이 모든 객체가 아닌 새로운 객체가 반입 될 때마다 발생합니다. – user1677663

+0

파이썬은 일반적인 개념을 반복자 (iterator)라고 부른다. 반복기는 프롬프트 될 때 한 번에 하나의 값을 생성합니다. 생성자 표현식은 생성자를 특수한 종류의 반복자로 만드는 생성기를 생성하는 구문입니다. 결과를 스트림이라고 부를 수는 있지만 파이썬이이 개념을 위해 어디에서나 사용하는 용어는 아닙니다. –

답변

2

당신은 진입을 통제하고 컨텍스트의 떠나해야합니다

다음은 예입니다. 생성자 표현식에는 더 넓은 컨텍스트 개념이 없으므로 생성기 표현식에 컨텍스트 관리자를 넣을 수없고 생성 될 때 자동으로 입력되도록 기대할 수 없습니다.

with 문은 실제 컨텍스트를 관리하며 CM에서는 __enter____exit__ 후크를 트리거합니다. 당신은 여기에 발전기 표현에서 생산 된 컨텍스트 관리자 개체를 사용할 수 있습니다 다음 with 문은 여기 cm.__enter__를 호출하고, 블록이 완료되면 cm.__exit__가 호출됩니다

def clean(): 
    for cm in (visitDir(p) for p in paths): 
     with cm as p: 
      print p 
      print os.getcwd() 

.

하지만 찾을 것보다 읽기 쉽고 이해하기 쉬운 다음

def clean(): 
    for p in paths: 
     with visitDir(p): 
      print p 
      print os.getcwd() 

with 라인의 일부로서 컨텍스트 관리자 만들기 따라하기 더욱 쉬워 때문이다.

+0

동의합니다. 최종 버전이 더 읽기 쉽습니다. 만약''cm만큼 p '라고 말할 필요가 없다면 광산은 가치가 있었을 것입니다. 그 여분의 선은 간결함/우아함을 잃어 버렸습니다. – user1677663