“제외 : 통과”가 나쁜 프로그래밍 관행 인 이유는 무엇입니까?


324

종종 사용 except: pass하지 않는 방법에 대한 다른 Stack Overflow 질문에 대한 의견이 있습니다 . 왜 이것이 나쁜가요? 때로는 오류가 무엇인지 신경 쓰지 않고 코드를 계속 사용하고 싶습니다.

try:
    something
except:
    pass

except: pass블록을 사용하는 것이 좋지 않습니까? 무엇이 나쁜가요? 내가 사실이다 pass오류 또는 내가 그 except오류?


1
최소한, 나는 당신이 그것을 기록 할 것을 제안하므로, 당신은 당신이 무시하고있는 문제를 알고 있습니다. loggingDEBUG 레벨에서 모듈을 사용하여 프로덕션 환경에서 스트리밍되지 않도록하고 개발에 사용 가능하게 유지하십시오.
pcurry

답변:


346

잡기 : 올바르게 추측, 그것은 두 가지 측면이 있습니다 어떤 후 예외 유형을 지정하지 의해 오류를 except, 단순히 어떤 조치를 취하기없이 통과가.

내 설명은 "약간"길다. 그래서 tl; dr 다음과 같이 분류된다.

  1. 캐치하지 마십시오 어떤 오류를 . 항상 복구 할 예외를 지정하고 예외 만 포착하십시오.
  2. 블록을 제외하고는지나 가지 않도록하십시오 . 명시 적으로 원하지 않는 한 이것은 일반적으로 좋은 신호가 아닙니다.

그러나 자세하게 살펴 보자.

캐치하지 마십시오 어떤 오류를

try블록을 사용할 때 예외가 발생할 가능성이 있다는 것을 알고 있기 때문에 일반적으로이 작업을 수행합니다. 따라서, 당신은 또한 무엇이 깨질 수 있고 어떤 예외가 던져 질 수 있는지에 대한 대략적인 아이디어를 가지고 있습니다. 이러한 경우, 긍정적으로 복구 할 수 있기 때문에 예외가 발생 합니다. 즉, 귀하는 예외에 대비하고 해당 예외에 대비하여 대체 계획을 마련해야합니다.

예를 들어, 사용자에게 숫자를 입력하도록 요청하면을 int()올릴 수있는를 사용하여 입력을 변환 할 수 있습니다 ValueError. 사용자에게 간단히 다시 시도하도록 요청하여이를 쉽게 복구 할 수 있으므로 사용자를 파악하고 ValueError다시 프롬프트하면 적절한 계획이됩니다. 다른 예는 파일에서 일부 구성을 읽으려는 경우 해당 파일이 존재하지 않는 경우입니다. 구성 파일이므로 대체로 일부 기본 구성이있을 수 있으므로 파일이 꼭 필요한 것은 아닙니다. 따라서 FileNotFoundError기본 구성을 간단히 적용하고 적용하는 것이 좋습니다. 이제 두 경우 모두, 우리는 우리가 기대하는 매우 특정한 예외를 가지고 있으며, 그것으로부터 회복 할 동등한 계획이 있습니다. 이와 같이, 각각의 경우에, 우리는 만 명시 적으로 except 특정이 예외.

그러나 우리가 모든 것을 잡아야한다면, 우리가 회복 할 준비가 된 예외 외에, 우리가 예상하지 못했던 예외가 생겨 실제로 회복 할 수없는 기회도있을 것입니다. 또는 회복해서는 안됩니다.

구성 파일 예제를 위에서 보자. 누락 된 파일의 경우 기본 구성을 적용한 후 나중에 자동으로 구성을 저장하기로 결정했을 수 있습니다 (다음에 파일이 존재 함). 이제 우리는 IsADirectoryError또는PermissionError대신에. 그러한 경우, 우리는 아마도 계속하고 싶지 않을 것입니다. 기본 구성을 계속 적용 할 수는 있지만 나중에 파일을 저장할 수 없습니다. 그리고 사용자가 사용자 정의 구성을 가지고 있었기 때문에 기본값을 사용하지 않는 것이 좋습니다. 따라서 사용자에게 즉시 알리고 프로그램 실행도 중단하려고합니다. 그러나 그것은 우리가 작은 코드 부분 내에서 깊게하고 싶은 것이 아닙니다. 이는 응용 프로그램 수준에서 중요하므로 맨 위에서 처리해야합니다. 따라서 예외가 발생하도록합니다.

또 다른 간단한 예는 Python 2 관용구 문서 에도 언급되어 있습니다. 여기에는 코드에 간단한 오타가있어 코드가 중단됩니다. 우리는 모든 예외를 잡기 때문에 NameErrorsSyntaxErrors 도 잡습니다 . 둘 다 프로그래밍하는 동안 우리 모두에게 발생하는 실수입니다. 그리고 둘 다 코드를 배송 할 때 절대 포함하고 싶지 않은 실수입니다. 그러나 우리는 또한 그것들을 잡았 기 때문에 그것들이 발생했다는 것을 알지 못하고 올바르게 디버깅하는 데 도움이 없습니다.

그러나 우리가 준비하지 않은 더 위험한 예외도 있습니다. 예를 들어 SystemError 는 일반적으로 거의 발생하지 않으며 실제로 계획 할 수없는 것입니다. 그것은 더 복잡한 일이 진행되고 있음을 의미하며, 현재 진행중인 작업을 계속하지 못할 수도 있습니다.

어쨌든 코드의 작은 부분으로 모든 것을 준비 할 가능성이 거의 없으므로 실제로는 예외를 잡아야합니다. 어떤 사람들은 적어도 캐치에 제안 Exception이 같은 것들을 포함되지 않습니다으로 SystemExit하고 KeyboardInterrupt있는 디자인으로 응용 프로그램을 종료 할 수 있습니다,하지만 난이 여전히 너무 불특정 것을 주장 할 것이다. 나는 개인적으로 잡기 동의를 하나의 장소가 Exception단지 또는 임의예외는 단일 전역 응용 프로그램 수준 예외 처리기에 있으며 준비되지 않은 예외를 기록하는 단일 목적이 있습니다. 이렇게하면 예기치 않은 예외에 대한 정보를 여전히 많이 보유 할 수 있습니다. 그런 다음 코드를 확장하여 명시 적으로 (복구 할 수있는 경우) 처리하거나 버그가있는 경우이를 처리하여 테스트 사례를 작성하여 확인할 수 있습니다. 다시는 발생하지 않습니다. 그러나 물론 우리가 이미 기대했던 예외를 잡은 경우에만 작동하므로 예상하지 않은 예외는 자연스럽게 발생합니다.

블록을 제외하고는지나 가지 않도록하십시오

소수의 특정 예외를 명시 적으로 포착 할 때 단순히 아무 것도하지 않아도되는 상황이 많이 있습니다. 그런 경우에는 그냥있는 except SomeSpecificException: pass것이 좋습니다. 그러나 대부분의 경우 복구 프로세스와 관련된 코드가 필요할 가능성이 높기 때문에 그렇지 않습니다 (위에서 언급 한 것처럼). 예를 들어 작업을 다시 시도하거나 기본값을 설정하는 것일 수 있습니다.

예를 들어 코드가 성공할 때까지 반복하도록 이미 구성되어 있기 때문에 그렇지 않은 경우 전달하는 것으로 충분합니다. 위의 예를 살펴보면 사용자에게 숫자를 입력하도록 요청할 수 있습니다. 우리는 사용자가 요청한 것을하지 않기를 원하기 때문에 처음에는 루프에 넣을 수 있으므로 다음과 같이 보일 수 있습니다.

def askForNumber ():
    while True:
        try:
            return int(input('Please enter a number: '))
        except ValueError:
            pass

예외가 발생하지 않을 때까지 계속 시도하기 때문에 except 블록에서 특별한 작업을 수행 할 필요가 없으므로 괜찮습니다. 그러나 물론 사용자에게 입력을 반복 해야하는 이유를 알려주는 오류 메시지를 표시하고 싶다고 주장 할 수 있습니다.

다른 많은 경우에, 그냥 전달하는 except것은 우리가 잡는 예외에 대해 실제로 준비되지 않았다는 신호입니다. 이러한 예외가 간단 ValueError하거나 (와 같이) 또는 TypeError통과 할 수있는 이유가 명백하지 않은 경우 통과하지 않도록 노력하십시오. 정말로 할 일이 없다면 (그리고 당신은 그것에 대해 절대적으로 확신한다면), 왜 그런지 설명을 추가하는 것을 고려하십시오; 그렇지 않으면, 복구 블록을 실제로 포함하도록 except 블록을 확장하십시오.

except: pass

최악의 범죄자는 둘 다의 조합입니다. 우리가 기꺼이 잡는 것을이 의미 있는 우리가 절대적으로 준비되지 않더라도 오류 우리는 또한 그것에 대해 아무것도 할 수 없습니다. 당신은 적어도 오류를 기록 할도 가능성이 여전히 응용 프로그램을 종료 할 리 레이즈 (당신이 MemoryError의 후 정상처럼 계속 확률이 낮다). 그냥 통과하면 응용 프로그램을 어느 정도 살아있게 유지할뿐만 아니라 (물론 잡는 위치에 따라) 모든 정보를 버려서 오류를 발견하는 것이 불가능합니다.


결론은 다음과 같습니다. 실제로 예상하고 복구 할 준비가 된 예외 만 포착하십시오. 다른 모든 것들은 당신이 고쳐야 할 실수이거나 어쨌든 준비되지 않은 것일 수 있습니다. 특정 전달실제로 예외를 수행 할 필요가없는 경우 예외를 하는 것이 좋습니다. 다른 모든 경우에, 그것은 단지 추정과 게으름의 표시 일뿐입니다. 그리고 당신은 분명히 그것을 고치고 싶습니다.


1
"적어도 오류를 기록하고 응용 프로그램을 종료하기 위해 오류를 다시 발생시킬 수 있습니다." 예외를 포착 한 후에도 계속 버블 링되도록 예외를 "후진"시키는 방법을 보여줄 수 있습니까? 이것은 예외로 인해 응용 프로그램을 강제 종료하는 동안 일부 사용자 정의 오류 메시지를 추가하는 데 유용합니다.
Gabriel Staples

1
이것은 명확하게 도와줍니다 : 그들은 담요를 사용 except하지만 raise인수없이 호출 하여 예외가 계속 발생하여 응용 프로그램을 종료시킵니다. 나는 그것을 좋아하지 : ianbicking.org/blog/2007/09/re-raising-exceptions.html . 담요를 사용하지 않는 규칙에 대한 확실한 예외처럼 보입니다 except.
Gabriel Staples

1
@GabrielStaples 그래, 잡은 예외는를 사용하여 다시 생각할 수있다 raise. 일반적으로 예외를 기록하기 위해 응용 프로그램 내의 일부 위치에서만이 작업을 수행합니다.
poke

이것은 훌륭합니다. 블록을 제외하고는 전달하지 마십시오. 나는 더 이해하기 쉬운 것, 특히 다른 사람들에게 그렇게 행동한다고 ​​말하고 싶습니다. 파이썬 눈을 가져와 코드를 검토하고 블록에 질문하는지 확인하십시오. 가독성이 핵심입니다.
radtek

262

여기서 주요 문제는 모든 오류를 무시한다는 것입니다. 메모리 부족, CPU 굽기, 사용자 중지, 프로그램 종료, Jabberwocky가 사용자를 죽이고 있습니다.

이것은 너무 길다. 당신은 "이 네트워크 오류를 무시하고 싶습니다"라고 생각합니다. 예기치 않은 문제가 발생 하면 코드가 자동으로 계속 진행되어 아무도 예측할 수없는 완전히 예측할 수없는 방식으로 중단됩니다.

따라서 일부 오류 만 무시하고 나머지는 통과하도록 제한해야합니다.


75

의사 코드를 실행 해도 문자 그대로 오류가 발생하지 않습니다.

try:
    something
except:
    pass

마치을 던지는 대신 완벽하게 유효한 코드 조각 인 것처럼 NameError. 이것이 당신이 원하는 것이 아니길 바랍니다.


51

“제외 : 통과”가 나쁜 프로그래밍 관행 인 이유는 무엇입니까?

왜 이것이 나쁜가요?

try:
    something
except:
    pass

이것은 포함, 가능한 모든 예외를 catch GeneratorExit, KeyboardInterrupt그리고 SystemExit- 당신은 아마 캐치하지 않으려는 예외한다. 잡기와 동일합니다 BaseException.

try:
    something
except BaseException:
    pass

이전 버전의 설명서는 다음 과 같이 말합니다 .

Python의 모든 오류는 예외를 발생 except:시키기 때문에를 사용 하면 많은 프로그래밍 오류를 런타임 문제처럼 보이게하여 디버깅 프로세스를 방해 할 수 있습니다.

파이썬 예외 계층

부모 예외 클래스를 잡으면 모든 자식 클래스도 잡습니다. 처리 할 수있는 예외 만 잡는 것이 훨씬 더 우아합니다.

다음은 Python 3 예외 계층 구조입니다. 정말로 모두 잡으시겠습니까? :

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StopAsyncIteration
      +-- ArithmeticError
      |    +-- FloatingPointError
      |    +-- OverflowError
      |    +-- ZeroDivisionError
      +-- AssertionError
      +-- AttributeError
      +-- BufferError
      +-- EOFError
      +-- ImportError
           +-- ModuleNotFoundError
      +-- LookupError
      |    +-- IndexError
      |    +-- KeyError
      +-- MemoryError
      +-- NameError
      |    +-- UnboundLocalError
      +-- OSError
      |    +-- BlockingIOError
      |    +-- ChildProcessError
      |    +-- ConnectionError
      |    |    +-- BrokenPipeError
      |    |    +-- ConnectionAbortedError
      |    |    +-- ConnectionRefusedError
      |    |    +-- ConnectionResetError
      |    +-- FileExistsError
      |    +-- FileNotFoundError
      |    +-- InterruptedError
      |    +-- IsADirectoryError
      |    +-- NotADirectoryError
      |    +-- PermissionError
      |    +-- ProcessLookupError
      |    +-- TimeoutError
      +-- ReferenceError
      +-- RuntimeError
      |    +-- NotImplementedError
      |    +-- RecursionError
      +-- SyntaxError
      |    +-- IndentationError
      |         +-- TabError
      +-- SystemError
      +-- TypeError
      +-- ValueError
      |    +-- UnicodeError
      |         +-- UnicodeDecodeError
      |         +-- UnicodeEncodeError
      |         +-- UnicodeTranslateError
      +-- Warning
           +-- DeprecationWarning
           +-- PendingDeprecationWarning
           +-- RuntimeWarning
           +-- SyntaxWarning
           +-- UserWarning
           +-- FutureWarning
           +-- ImportWarning
           +-- UnicodeWarning
           +-- BytesWarning
           +-- ResourceWarning

이러지마

이 형태의 예외 처리를 사용하는 경우 :

try:
    something
except: # don't just do a bare except!
    pass

그런 다음 somethingCtrl-C로 블록 을 중단 할 수 없습니다 . 귀하의 프로그램은 내부의 가능한 모든 예외를 간과합니다try 코드 블록 .

다음은 바람직하지 않은 동작을하는 또 다른 예입니다.

except BaseException as e: # don't do this either - same as bare!
    logging.info(e)

대신, 당신이 찾고있는 특정 예외 만 잡으려고 노력하십시오. 예를 들어 전환시 가치 오류가 발생할 수 있음을 알고있는 경우 :

try:
    foo = operation_that_includes_int(foo)
except ValueError as e:
    if fatal_condition(): # You can raise the exception if it's bad,
        logging.info(e)   # but if it's fatal every time,
        raise             # you probably should just not catch it.
    else:                 # Only catch exceptions you are prepared to handle.
        foo = 0           # Here we simply assign foo to 0 and continue. 

다른 예를 가진 추가 설명

웹 스크래핑을하고 있고 UnicodeError 있기 때문에 그렇게 할 수 있지만, 가장 광범위한 예외 잡기를 사용했기 때문에 다른 근본적인 결함이있을 수있는 코드가 대역폭을 낭비하려고합니다. , 처리 시간, 장비 마모, 메모리 부족, 가비지 데이터 수집 등

다른 사람들이 귀하의 코드에 의존 할 수 있도록 완료하도록 요청하는 경우 모든 것을 처리해야한다는 느낌을받습니다. 그러나 개발하면서 소음에 시달리게 실패한다면 간헐적으로 발생할 수있는 문제를 해결할 수있는 기회가 있지만 장기적으로 많은 비용이 드는 버그 일 것입니다.

보다 정확한 오류 처리를 통해 코드를 더욱 강력하게 만들 수 있습니다.


31
>>> import this

파이썬의 선 (The Zen of Python), Tim Peters

못생긴 것보다 아름답습니다.
암시적인 것보다 명시적인 것이 좋습니다.
단순함이 복잡한 것보다 낫습니다.
복잡한 것이 복잡한 것보다 낫습니다.
평평한 것이 중첩보다 낫습니다.
스파 스가 밀도보다 낫습니다.
가독성이 중요합니다.
특별한 경우는 규칙을 어길만큼 특별하지 않습니다.
실용성은 순도를 능가하지만.
오류가 자동으로 전달되지 않아야합니다.
명시 적으로 침묵하지 않는 한.
모호함에 직면하여 추측하려는 유혹을 거부하십시오.
그것을하는 명백한 방법이 있어야합니다.
네덜란드 인이 아니라면 처음에는 그 방법이 명확하지 않을 수 있습니다. 바로 지금
지금보다 결코 낫습니다.
결코 결코 낫지 않지만
구현이 설명하기 어렵다면 나쁜 생각입니다.
구현이 설명하기 쉬운 경우 좋은 생각 일 수 있습니다.
네임 스페이스는 훌륭한 아이디어 중 하나입니다. 더 많은 것을 해보자!

자, 여기 내 의견이 있습니다. 오류를 발견 할 때마다 처리 할 작업을 수행해야합니다 (예 : 로그 파일이나 다른 것에 작성). 적어도 오류가 발생했음을 알려줍니다.


64
-1 권위의 주장은 실제로 아무 것도 설명 하지 않습니다 . 권위가 잘못 될 수 있습니다.
이즈 카타

23
@Izkata가 쓴 것, 그리고 그 아래 한 줄에 같은 권한이 있습니다. "명시 적으로 침묵하지 않는 한".
Ofri Raviv 2019

13
@OfriRaviv 아니요, 오류가 암시 적으로 전달되지 않습니까? 명시 적으로 전달해야하는 오류의 이름을 명시 적으로 지정해야 합니다 . 이것은 pass가 제외하는 것이 아닙니다.
Chelonian 2019

24

당신은 적어도 사용해야합니다 except Exception:같은 시스템 예외를 잡는 피하기 위해 SystemExit또는 KeyboardInterrupt. 문서에 대한 링크 입니다.

일반적으로 원하지 않는 예외를 포착하지 않도록 명시 적으로 포착하려는 예외를 정의해야합니다. 어떤 예외를 무시 해야하는지 알아야합니다 .


13

첫째, 그것은 Zen of Python 의 두 가지 원칙을 위반합니다 .

  • 암시 적보다 묵시적이다
  • 오류는 조용히지나 가지 않아야합니다

의미하는 것은 의도적으로 오류를 자동으로 전달한다는 것입니다. 또한, 정확히 어떤 오류가 발생했는지 알 수 없습니다.except: pass 예외를 잡을 수 .

둘째, 우리가 파이썬의 선 (Zen of Python)에서 벗어나려고 시도하고, 단지 온전한 용어로 말하면, 사용 except:pass하면 시스템에 대한 지식과 통제력이 없어진다는 것을 알아야 합니다. 경험상 오류가 발생하면 예외를 발생시키고 적절한 조치를 취하는 것입니다. 미리 알지 못하는 경우 어떤 조치를 취해야하는지 적어도 어딘가에 오류를 기록하십시오 (예외를 개선하는 것이 좋습니다).

try:
    something
except:
    logger.exception('Something happened')

그러나 일반적으로 예외를 잡으려고하면 뭔가 잘못한 것일 수 있습니다.


2
... 명시 적으로 침묵하지 않는 한, OP의 경우입니다.
Hyperboreus

귀하의 솔루션을 알고 싶습니다. 실제로 실제로 아무것도 할 필요가없는 경우에는 오류를 나열하고 주석을 작성하고 로그를 작성합니다. 그런 다음 통과하십시오.
Booster

2
@Hyperboreus, 나는 모든 오류를 잡는 것이 명시 적으로 그것들을 침묵시키는 것이라고 생각하지 않습니다.
Alexander Zhukov

13
"어떤 사람이 그렇게 말했기 때문에"는 "왜?" 질문.
Sebastian Negraszus

12

except:pass구조는 본질적으로 덮여 코드 동안 올 일체의 예외 조건 침묵 try:블록이 실행 중입니다.

이 나쁜 습관을 만드는 것은 보통 그것이 실제로 원하는 것이 아니라는 것입니다. 더 자주, 당신이 침묵하고 싶은 특정 조건이 나타나고 except:pass너무 무딘 악기입니다. 작업이 완료되지만 예상치 못한 다른 오류 조건을 가리지 만 다른 방식으로 처리하고 싶을 수도 있습니다.

파이썬에서 이것을 특히 중요하게 만드는 것은이 언어의 관용구에 의해 예외가 반드시 오류 일 필요는 없다는 것 입니다. 물론 대부분의 언어와 마찬가지로 이러한 방식으로 자주 사용됩니다. 그러나 파이썬은 특히 실제 실행 사례의 일부가 아니지만 때때로 때때로 나타나며 대부분의 경우에 예상되는 일부 코드 작업의 대체 종료 경로를 구현하는 데 종종이를 사용했습니다. SystemExit이전 예제로 이미 언급되었지만 요즘 가장 일반적인 예는입니다 StopIteration. 이 방법으로 예외를 사용하면 반복자와 생성기가 처음 Python에 도입되었을 때 많은 논란이 있었지만 결국 아이디어가 우세했습니다.


12

# 1 이유는 이미 언급되었으므로 예상치 못한 오류를 숨 깁니다.

(# 2)- 다른 사람이 읽고 이해하기 어려운 코드입니다. 파일을 읽으려고 할 때 FileNotFoundException을 발견하면 다른 개발자에게 'catch'블록의 기능이 분명합니다. 예외를 지정하지 않으면 블록의 기능을 설명하기 위해 추가 설명이 필요합니다.

(# 3)- 게으른 프로그래밍을 보여줍니다. 일반 try / catch를 사용하는 경우 프로그램에서 발생 가능한 런타임 오류를 이해하지 못했거나 Python에서 어떤 예외가 가능한지 알 수 없음을 나타냅니다. 특정 오류를 포착하면 프로그램과 Python에서 발생하는 오류 범위를 모두 이해할 수 있습니다. 다른 개발자와 코드 검토자가 작업을 신뢰하게 만들 가능성이 높습니다.


12

이 코드는 어떤 출력을 생성합니까?

fruits = [ 'apple', 'pear', 'carrot', 'banana' ]

found = False
try:
     for i in range(len(fruit)):
         if fruits[i] == 'apple':
             found = true
except:
     pass

if found:
    print "Found an apple"
else:
    print "No apples in list"

이제 상상 try- except블록은 복잡한 객체 계층 구조에 대한 호출 수백 줄의, 그리고 자체가 큰 프로그램의 호출 트리의 중간에 호출된다. 프로그램이 잘못되면 어디에서 시작합니까?


5
어, 이것을 '수정 한'사람들에게 감사하지만,하지 말아주세요. 의도적으로 '면접 질문'의 의미에서 잘못되었습니다. 처음 나타나는 것이 더 미묘 할 수도 있습니다. 시도해보십시오. 필자의 요점은 특히 파이썬에서 '모든'예외를 스쿼시하면 사소한 수십 줄의 코드에서도 디버깅이 어렵다는 것입니다.
Ian Harvey

11

일반적으로 오류 / 예외를 다음 중 하나로 분류 할 수 있습니다. 세 가지 범주 .

  • 치명적 : 당신의 잘못이 아니라 예방할 수 없으며 회복 할 수 없습니다. 확실히 무시하고 계속하지 말고 프로그램을 알 수없는 상태로 두십시오. 오류로 인해 프로그램이 종료되도록하십시오. 수행 할 수있는 작업이 없습니다.

  • 뼈가 : 감독, 버그 또는 프로그래밍 오류로 인한 자체 오류. 버그를 수정해야합니다. 다시, 당신은 가장 무시하고 계속해서는 안됩니다.

  • 외생 : 파일을 찾을 수 없거나 연결이 종료 된 경우와 같은 예외적 인 상황에서 이러한 오류가 발생할 수 있습니다 . 이러한 오류를 명시 적으로 처리해야합니다.

모든 경우에 except: pass프로그램은 알 수없는 상태로 남겨져 더 많은 손상을 일으킬 수 있습니다.


6

간단히 말해서 예외 나 오류가 발생하면 문제가있는 것입니다. 매우 잘못된 것은 아니지만 goto 문을 사용하기 위해 오류와 예외를 만들고 던지고 포착하는 것은 좋은 생각이 아니며 거의 이루어지지 않습니다. 시간의 99 %, 어딘가에 문제가있었습니다.

문제를 해결해야합니다. 인생에서와 마찬가지로, 프로그래밍에서, 문제를 홀로 남겨두고 무시하려고한다면, 그들은 스스로 많은 시간을 버리지 않습니다. 대신 그들은 더 커지고 배가됩니다. 문제가 발생하지 않고 도로에서 다시 내려가는 것을 방지하려면 1) 문제를 제거하고 나중에 엉망을 정리하거나 2) 문제를 해결하고 나중에 엉망을 정리하십시오.

예외와 오류를 무시하고 그대로 두는 것은 메모리 누수, 뛰어난 데이터베이스 연결, 불필요한 파일 권한 잠금 등을 경험하는 좋은 방법입니다.

드문 경우지만, 문제는 매우 사소하고 사소하며, 자체 포함 된 try ... catch 블록을 제외하고는 나중에 정리할 혼란이 전혀 없습니다. 이 모범 사례가 반드시 적용되는 것은 아닙니다. 내 경험상 이것은 일반적으로 코드가 수행하는 모든 것이 기본적으로 사소하고 잊을 수 없음을 의미하며 재시도 또는 특수 메시지와 같은 것은 복잡하거나 스레드를 유지할 가치가 없습니다.

우리 회사의 규칙은 거의 항상 catch 블록에서 무언가 를 수행하는 것이며, 아무것도하지 않으면 항상 이유가없는 아주 좋은 이유가있는 코멘트를 달아야합니다. 해야 할 일이있을 때 절대 빈 캐치 블록을 통과하거나 떠나지 않아야합니다.


6

내 의견으로는 오류가 나타나야 할 이유가 있습니다. 좋은 프로그래밍은 오류를 처리해야 할 때만 오류를 발생시킵니다. 또한, 얼마 전에 읽은 것처럼 "pass-Statement는 나중에 코드가 삽입되는 것을 보여주는 Statement입니다"이므로 빈 예외 명령문을 원한다면 자유롭게 입력하십시오. 그러나 좋은 프로그램을 위해서는 부품이 누락되었습니다. 당신이해야 할 것들을 처리하지 않기 때문에. 나타나는 예외는 입력 데이터를 수정하거나 데이터 구조를 변경하여 이러한 예외가 다시 발생하지 않도록 할 수있는 기회를 제공하지만 (대부분의 경우 (네트워크 예외, 일반 입력 예외) 예외는 프로그램의 다음 부분이 제대로 실행되지 않음을 나타냅니다. 예를 들어 NetworkException은 네트워크 연결이 끊어 졌음을 나타내며 프로그램은 다음 프로그램 단계에서 데이터를 보내거나받을 수 없습니다.

그러나 하나의 execption-block에만 패스 블록을 사용하는 것이 유효합니다. 예외 유형 사이에서 여전히 차이가 있기 때문에 모든 예외 블록을 하나로 묶으면 비어 있지 않습니다.

try:
    #code here
except Error1:
    #exception handle1

except Error2:
    #exception handle2
#and so on

그런 식으로 다시 쓸 수 있습니다 :

try:
    #code here
except BaseException as e:
    if isinstance(e, Error1):
        #exception handle1

    elif isinstance(e, Error2):
        #exception handle2

    ...

    else:
        raise

따라서 pass-statement를 가진 여러 개의 except-block조차도 코드를 만들 수 있으며, 그 구조는 특수한 유형의 예외를 처리합니다.


4

지금까지 제기 된 모든 의견은 유효합니다. 가능한 경우 정확히 무시하려는 예외를 지정해야합니다. 가능한 경우 예외를 일으킨 원인을 분석하고 나머지는 무시하고 무시하려는 대상 만 무시해야합니다. 예외로 인해 응용 프로그램이 "놀랍게 충돌"하게되면 예상치 못한 일이 발생했을 때 문제가 발생했음을 숨기는 것보다 아는 것이 훨씬 더 중요하기 때문입니다.

모든 말로, 프로그래밍 연습을 최우선으로 생각하지 마십시오. 이것은 바보입니다. 항상 모든 예외 무시 블록을 수행 할 시간과 장소가 있습니다.

이디 오 파라마운트의 또 다른 예는 goto연산자 사용법입니다 . 내가 학교에있을 때, 교수님은 goto운영자 에게 절대로 사용하지 말라고 언급 하라고 지시했습니다. xyz를 절대 사용해서는 안되며 유용한 시나리오가있을 수 있다고 말하는 사람들을 믿지 마십시오. 항상 있습니다.


1
"고토 (goto)"사례는 문체 적이며 의견의 문제이지만 "제외 : 통과 (pass)"는 대개 사실이 아닙니다. 예를 들어 누군가가 그 시점에서 프로세스를 "kill -TERM"해야한다면 무시해야한다고 가정합니다. 최소한 그것은 나쁜 행동입니다.
Score_Under

1
@Score_하지만 아직 이것이 사용하기에 적합한 경우가 있습니다. 예를 들어, 호출중인 함수가 보조 기능이고 알려지지 않은 출처 / 작성자 인 경우 핵심 기능에는 영향을 미치지 않지만 충돌이 문제를 일으킬 수있는 경우입니다. 그러한 전화가 제대로 연구되고 분석되어야한다고 주장하지만 실제로는 항상 가능하지는 않습니다.
galets

여전히 프로세스를 종료하려면 kill -9가 유일한 신뢰할 수있는 옵션이 아닙니다.
Score_Unders

2

프로그래밍에서 오류 처리는 매우 중요합니다. 사용자에게 무엇이 잘못되었는지 표시해야합니다. 매우 적은 경우에 오류를 무시할 수 있습니다. 이것은 매우 나쁜 프로그래밍 관행입니다.


2

아직 언급되지 않았으므로 사용하는 것이 더 좋습니다 contextlib.suppress.

with suppress(FileNotFoundError):
    os.remove('somefile.tmp')

제공된 예제 에서 프로그램 상태는 예외 발생 여부에 관계없이 동일하게 유지됩니다. 즉, somefile.tmp항상 존재하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.