2014-10-28 2 views
6

에서 파일을 닫는 I 읽고는, 해당 파일이 자동으로 닫힙니다과 같이 열 :파이썬

from contextlib import closing 
from urllib.request import urlopen 

with closing(urlopen('http://www.python.org')) as page: 
    for line in page: 
     print(line) 
:

with open("x.txt") as f: 
    data = f.read() 
    do something with data 

아직 웹에서 열 때, 나는이 필요

왜 그 차이가 있습니까? (저는 Python3을 사용하고 있습니다)

+0

나는 누군가가 이것을 위해'contextlib'에 문서 버그를 제출해야한다는 것을 제안하려고했는데, 만약 당신이 누구 이건 당신에게 신용을 주어야한다고 ... 그러나 끝낼 수 있기 전에, Martijn은 벌써 버그를 링크와 함께 제출했다. 여기로. :) – abarnert

답변

6

세부 사항은 약간의 기술적 얻을, 그래서 간단한 버전으로 시작하자 :

일부 유형은 with 문에 사용되는 방법을 알고있다. open에서 반환하는 것과 같은 파일 객체는 이러한 유형의 예입니다. 밝혀진 바와 같이, urllib.request.urlopen에서 되돌아온 객체는 이고 이러한 두 번째 예제는 첫 번째 예제와 같은 방식으로 작성 될 수 있습니다.

그러나 일부 유형은 with 문에 사용하는 방법을 알지 못합니다.closing 함수는 close 메서드를 사용하는 경우 이러한 형식을 래핑하도록 디자인되었으므로 with 문을 종료 할 때 close 메서드를 호출합니다. 자신의 정리 방법은 close 이름 (또는하지 않기 때문에 일부 유형은 또한 with 문에서 사용하는 방법을 알고하지 않습니다 물론

closing 사용할 수 없습니다를 청소 단지보다 더 복잡하기 때문에 그들을 폐쇄). 이 경우 사용자 정의 컨텍스트 관리자를 작성해야합니다. 그러나 심지어 그렇게 어렵지도 않습니다. 기술적 인 용어로


:

with 문은 context manager, __enter____exit__ 방법과 객체가 필요합니다. __enter__ 메서드를 호출하고 as 절에 해당 메서드에서 반환 된 값을 제공하면 with 문 끝에 __exit__ 메서드가 호출됩니다.

파일 개체는 __enter__ 메서드를 반환하는 컨텍스트 관리자 인 io.IOBase에서 상속받으며 __exit__self.close()을 호출합니다.

urlopen 의해 리턴 된 객체는 문서 말했듯 "고 진술 with 함께 사용할 수있는,"HTTPResponse, (AN httphttps URL 또는 가정)이다.

closing 기능 :

돌아 블록이 완료되면 일을 닫는 상황 매니저. 이것은 기본적으로 동일합니다 :

@contextmanager 
def closing(thing): 
    try: 
     yield thing 
    finally: 
     thing.close() 

그것의 종류의 상황에 맞는 관리자이며, 종류가 아닌 문서에서 항상 100 % 취소합니다. 특히 컨텍스트 관리자가 될 수있는 모든 것을 만들기 위해 3.1 이후 주요한 드라이브가 있었기 때문에 (그리고 의미가있는 경우 대부분은 파일과 같은 모든 것을 실제의 IOBase으로 만들었습니다.) 그러나 여전히 그렇지 않습니다. 3.4에서 100 % 완료.

언제든지 시도해보고 볼 수 있습니다. AttributeError: __exit__이 있으면 오브젝트를 컨텍스트 매니저로 사용할 수 없습니다. 그것이 있어야한다고 생각되면 변경을 제안하는 버그를 제출하십시오. 이 오류가 발생하지 않았지만 문서에 합법적이라고 언급되지 않으면 문서를 업데이트하라는 버그를 제출하십시오.

+0

자세한 설명에 감사드립니다! – nekomimi

7

당신은하지 않습니다. urlopen('http://www.python.org') 반환 너무 컨텍스트 관리자 :이 urllib.request.urlopen() page에 설명되어 있습니다

with urlopen('http://www.python.org') as page: 

:

FTP, 파일 및 데이터 URL의

및 레거시 URLopenerFancyURLopener 클래스에 의해 처리 명시 적으로는,이 함수가 반환하는 요청 urllib.response.addinfourl 오브젝트 컨텍스트 매니저 [...]로 작업 할 수 있습니다.

강조 광산.

응답은 반복 가능한 객체이고 으로 사용할 수 있습니다 : HTTP 응답의 경우, http.client.HTTPResponse() object 또한 컨텍스트 매니저 인 반환됩니다. 메타 태그, 우리는 바이트를 디코딩 같은 사용의 IT에 규정 된 python.org 웹 사이트가 UTF-8 인코딩을 사용하기 때문에

:

Examples section

는 컨텍스트 매니저로 오브젝트를 사용 목적. open()에 의해 반환

>>> with urllib.request.urlopen('http://www.python.org/') as f: 
...  print(f.read(100).decode('utf-8')) 
... 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtm 

객체가 너무 context managers이다; 특수 메서드 object.__enter__()object.__exit__()을 구현합니다.

contextlib.closing() documentationurlopen()의 예를 사용합니다. 파이썬 2에서 이전 버전 인 urllib.request.urlopen()은 컨텍스트 관리자를 생성하지 않았으며이 도구를 사용하여 컨텍스트 관리자와의 연결을 자동으로 닫아야했습니다. 이 문제는 541812365으로 수정되었지만 해당 예제는 업데이트되지 않았습니다. 다른 예제를 묻는 issue 22755을 만들었습니다.

+0

나는 이것을 쓰려고하고 있었다. :-). 핵심은 문서가 "파일 형"객체를 반환한다고 말합니다. 컨텍스트 관리자로 사용할 수 없으면 실제로 파일과 유사하지 않습니다. – mgilson

+0

하지만 왜 python docs에이 예제가 있습니까? https://docs.python.org/3/library/contextlib.html – nekomimi

+1

@nekomimi : 객체가 컨텍스트 관리자가 아닌 곳에서 Python 2의 잔류 물이있는 것 같습니다. –