try-except 블록과 함께 파이썬 "with"문 사용


96

이것은 try-except 블록과 함께 파이썬 "with"문을 사용하는 올바른 방법입니까? :

try:
    with open("file", "r") as f:
        line = f.readline()
except IOError:
    <whatever>

그렇다면 이전 작업 방식을 고려하십시오.

try:
    f = open("file", "r")
    line = f.readline()
except IOError:
    <whatever>
finally:
    f.close()

세 줄의 코드를 제거 할 수 있다는 "with"문의 주요 이점이 있습니까? 이 사용 사례에 대해서는 그다지 매력적이지 않은 것 같습니다 ( "with"문에 다른 용도가 있음을 이해합니다).

편집 : 위의 두 코드 블록의 기능이 동일합니까?

EDIT2 : 처음 몇 개의 답변은 일반적으로 "with"사용의 이점에 대해 이야기하지만 여기서는 약간의 이점이있는 것 같습니다. 우리는 모두 수년 동안 명시 적으로 f.close ()를 호출 해 왔습니다 (또는 그래야만 했어야합니다). 한 가지 이점은 엉성한 코더가 "with"를 사용하면 도움이된다는 것입니다.



나에게는 finally 문에서 close () 항목을 기억할 필요가 없다는 것이 'with'를 사용할 충분한 이유입니다. 많은 코드가 리소스를 닫지 못하는 것을 보았습니다. 그리고 'with'는 내가 볼 수있는 한 단점이 없습니다.
Raúl Salinas-Monteagudo

답변:


139
  1. 제공 한 두 개의 코드 블록이 동일 하지 않습니다.
  2. 예전 방식으로 설명한 코드 에는 심각한 버그가 있습니다. 파일 열기에 실패하면 바운드가 아니기 finally때문에 절 에서 두 번째 예외가 발생합니다 f.

동등한 이전 스타일 코드는 다음과 같습니다.

try:
    f = open("file", "r")
    try:
        line = f.readline()
    finally:
        f.close()
except IOError:
    <whatever>

보시 with다시피이 명령문은 오류 발생 가능성을 줄입니다. 최신 버전의 Python (2.7, 3.1)에서는 여러 식을 하나의 with문으로 결합 할 수도 있습니다 . 예를 들면 :

with open("input", "r") as inp, open("output", "w") as out:
    out.write(inp.read())

그 외에도 가능한 한 빨리 예외를 포착하는 것이 개인적으로 나쁜 습관이라고 생각합니다. 이것은 예외의 목적이 아닙니다. 실패 할 수있는 IO 함수가 더 복잡한 작업의 일부인 경우 대부분의 경우 IOError는 전체 작업을 중단해야하므로 외부 수준에서 처리해야합니다. with문을 사용하면 try...finally내부 수준에서 이러한 모든 문을 제거 할 수 있습니다.


7

finally블록 의 내용 이 열려있는 파일 객체의 속성에 의해 결정되는 경우 파일 객체의 구현자가 finally블록 을 작성하지 않아야하는 이유는 무엇입니까? 이것이이with 특정 인스턴스에서 세 줄의 코드를 절약하는 것보다 훨씬 더 많은 명령문 의 이점입니다 .

그리고 네, 당신은 조합 한 방법 with과는 try-except예외적 인 오류가 내 원인으로 할 수있는 유일한 방법은, 꽤 많이 open자체가 내 잡힐 수없는 문 with블록.


1

줄만 줄인다는 "with"문이 틀렸다고 생각합니다. 실제로 초기화를 수행하고 분해를 처리합니다.

귀하의 경우 "with"는

  • 파일을 열고
  • 그 내용을 처리하고
  • 닫아야합니다.

다음은 "with"문을 이해하기위한 링크입니다. http://effbot.org/zone/python-with-statement.htm

편집 : 예 "with"사용이 정확하고 두 코드 블록의 기능이 동일합니다. "with"를 사용하는 이유에 대한 질문? 그것은 당신이 그것으로 얻는 이점 때문입니다. 실수로 누락 된 f.close ()에 대해 언급했듯이.


-4

다음 코드에 대한 더 Pythonic 방법은 다음과 같습니다.

try:
    f = open("file", "r")
    try:
        line = f.readline()
    finally:
        f.close()
except IOError:
    <whatever>

try:
    f = open("file", "r")
except IOError:
    <whatever>
else:
    f.close()

1
나는 당신을 위해 코드 서식을 추가했습니다. 읽기가 더 쉽습니다. 그러나 들여 쓰기가 깨지지 않았는지 다시 확인하고 싶을 수도 있습니다.
andrewsi

2
아니요, 귀하의 버전은 원래 코드와 동일한 작업을 수행하지 않습니다. 누락 된 readline()호출 을 추가하더라도 readline()결과가 IOError.
Aleksi Torhamo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.