source

어떤 것을 '시도'하고 예외를 포착하거나 예외를 피하는 것이 먼저 가능한지 테스트하는 것이 더 낫습니까?

gigabyte 2023. 7. 18. 23:08
반응형

어떤 것을 '시도'하고 예외를 포착하거나 예외를 피하는 것이 먼저 가능한지 테스트하는 것이 더 낫습니까?

가 트해볼요까테를 테스트해 봐야 합니까?if 무가가유정당니다합나거효하언다▁something▁is정▁or▁valid니▁just.try그것을 하고 예외를 잡는 것?

  • 한 가지 방법이 선호된다는 확실한 문서가 있습니까?
  • 가지 방법이 더 비단결적인가요?

예를 들어, 다음과 같이 해야 합니다.

if len(my_list) >= 4:
    x = my_list[3]
else:
    x = 'NO_ABC'

또는:

try:
    x = my_list[3]
except IndexError:
    x = 'NO_ABC'

어떤 생각들은...
PEP 20은 다음과 같이 말합니다.

오류는 절대 조용히 전달되어서는 안 됩니다.
명시적으로 침묵하지 않는 한.

를사야합니다해를 사용해야 .try신에대 if소리 없이 전달되는 오류로 해석됩니까?만약 그렇다면, 당신은 이런 식으로 그것을 사용함으로써 그것을 확실히 침묵시키고, 그래서 그것을 괜찮게 만드는 것입니까?


저는 일을 한 가지 방법으로만 할 수 있는 상황을 말하는 것이 아닙니다. 예를 들어 다음과 같습니다.

try:
    import foo
except ImportError:
    import baz

은 당은선야합니다해호신합다▁prefer니▁should를 선호해야 합니다.try/except1파운드가 if/else그렇게 되면

  • 속도 향상(예: 추가 검색 방지)
  • 클리너 코드(읽을 수 있는 줄/글꼴 표시)

종종, 이것들은 손에 잡힙니다.


속도 향상

긴 목록에서 다음 방법으로 요소를 찾으려는 경우:

try:
    x = my_list[index]
except IndexError:
    x = 'NO_ABC'

시도, 제외하는 것이 가장 좋은 옵션입니다.index이 목록에 있을 수 있으며 인덱스 오류는 일반적으로 발생하지 않습니다.이렇게 하면 추가 검색이 필요하지 않습니다.if index < len(my_list).

Python은 예외를 사용할 것을 권장합니다. 이 예외Dive Into Python의 구문입니다.예제에서는 예외를 자동으로 통과시키지 않고 우아하게 처리할 뿐만 아니라 인덱스를 찾을 수 없는 예외적인 경우에만 예외가 발생합니다(따라서 exception!).


클리너 코드

공식 Python Documentation은 EAFP: 허가보다 용서를 구하는 것이 더 쉽다고 언급하고 Rob Knight는 오류를 피하는 대신 오류를 잡는 것이 더 깨끗하고 코드를 읽기 쉽게 만들 수 있다고 지적합니다.그의 예는 다음과 같이 말합니다.

더 나쁜 것 (LBIL '뛰기 전에 살펴라'):

#check whether int conversion will raise an error
if not isinstance(s, str) or not s.isdigit():
    return None
elif len(s) > 10:    #too many digits for int conversion
    return None
else:
    return int(s)

더 나은(EAFP: 허락보다 용서를 구하는 것이 더 쉽습니다):

try:
    return int(s)
except (TypeError, ValueError, OverflowError): #int conversion failed
    return None

이 경우에는 완전히 다른 것을 사용해야 합니다.

x = myDict.get("ABC", "NO_ABC")

그러나 일반적으로:테스트가 자주 실패할 것으로 예상되는 경우if 것에 비용이 ▁if▁use다▁relative니사▁is테합용▁test▁if스▁and▁expensive▁the▁exception▁operation▁the▁trying▁just▁catching▁to▁the을음다를 사용합니다.try이 두 가지 조건이 모두 적용되지 않는 경우 더 쉽게 읽을 수 있습니다.

용사를 합니다.try그리고.except내부보다는 직접적으로if레이스 상태가 발생할 가능성이 있는 경우 항상 가드를 수행해야 합니다.예를 들어 디렉토리가 있는지 확인하려면 다음 작업을 수행하지 마십시오.

import os, sys
if not os.path.isdir('foo'):
  try:
    os.mkdir('foo')
  except OSError, e
    print e
    sys.exit(1)

다른 스레드 또는 프로세스가 다음 사이에 디렉토리를 작성하는 경우isdir그리고.mkdir당신은 퇴장할 것입니다.대신 다음 작업을 수행합니다.

import os, sys, errno
try:
  os.mkdir('foo')
except OSError, e
  if e.errno != errno.EEXIST:
    print e
    sys.exit(1)

'foo' 디렉터리를 만들 수 없는 경우에만 종료됩니다.

만약 당신이 그것을 하기 전에 어떤 것이 실패할지를 확인하는 것이 사소한 것이라면, 당신은 아마도 그것을 선호해야 할 것입니다.결국 예외(관련된 추적백 포함)를 구성하는 데 시간이 걸립니다.

다음의 경우 예외를 사용해야 합니다.

  1. 예상치 못한 것들, 또는...
  2. a 나이상의예논수하것뛰들는야어어넘을준리하예▁a)▁a것(▁(들▁where▁things하▁you▁of▁more(a)))break충분히 멀리 가지 못합니다.) 또는...
  3. 사전에 무엇이 예외 사항을 처리할지 정확히 모르는 경우 또는...
  4. 사전에 고장 여부를 확인하는 데 비용이 많이 드는 작업(단순히 작업을 시도하는 것보다 비용이 더 많이 드는 작업)

종종 실제 대답은 "둘 다 아니다"입니다. 예를 들어, 첫 번째 예에서, 당신이 정말로 해야 할 일은 단지 사용하는 것입니다..get()기본값을 제공합니다.

x = myDict.get('ABC', 'NO_ABC')

다른 게시물에서도 언급했듯이, 상황에 따라 다릅니다.특히 대규모 프로젝트에서 데이터를 사용할 때 데이터의 유효성을 미리 확인하는 대신 try/를 사용하면 몇 가지 위험이 있습니다.

  • 시도 블록의 코드는 예외가 포착되기 전에 모든 종류의 혼란을 일으킬 수 있습니다. 만약 당신이 if 문으로 사전에 확인한다면 당신은 이것을 피할 수 있습니다.
  • TypeError(유형 오류) 또는 ValueError(값 오류)와 같은 일반적인 예외 유형을 호출한 경우, 예상했던 것과 동일한 예외를 실제로 감지하지 못할 수 있습니다. 예외가 발생할 수 있는 선에 도달하기 전이나 후에도 동일한 예외 클래스를 발생시킬 수 있습니다.

예를 들어, 다음과 같이 가정합니다.

try:
    x = my_list[index_list[3]]
except IndexError:
    x = 'NO_ABC'

IndexError는 index_list 또는 my_list 요소를 가져올 때 발생했는지 여부에 대해 아무 말도 하지 않습니다.

if 대신 try를 사용하는 것이 자동으로 전달되는 오류로 해석되어야 합니까?만약 그렇다면, 당신은 이런 식으로 그것을 사용함으로써 그것을 확실히 침묵시키고, 그래서 그것을 괜찮게 만드는 것입니까?

용사를 합니다.try오류가 전달될 수 있음을 인식하는 것으로, 오류를 자동으로 전달하는 것과 반대됩니다.용사를 합니다.except전혀 통과하지 못하게 만들고 있습니다.

용사를 합니다.try: except:다음과 같은 경우 선호됩니다.if: else:논리는 더 복잡합니다.단순함이 복잡함보다 낫고, 복잡함이 복잡함보다 낫고, 용서를 구하는 것이 허락보다 쉽습니다.

"오류는 절대 조용히 지나가지 말아야 한다"는 경고는 코드가 당신이 알고 있는 예외를 제기할 수 있는 경우와 당신의 설계가 가능성을 인정하지만 예외를 처리하는 방식으로 설계하지 않은 경우입니다.내가 보기에, 오류를 명시적으로 침묵시키는 것은 다음과 같은 일을 하는 것입니다.pass순식간에except블록 (block) 아정상이 "무것하않것는" 바올오른합류수니다야행어되하인만에서은 (가 잘 된 코드의 로 필요하다고 몇 번입니다.)(이것은 제가 잘 작성된 코드의 코멘트가 정말로 필요하다고 느끼는 몇 안 되는 경우 중 하나입니다.)

그러나 특정 예제에서는 둘 다 적절하지 않습니다.

x = myDict.get('ABC', 'NO_ABC')

여러분이 일반적으로 이해하려는 욕구와 더 나은 예를 제시할 수 없다는 것을 인정하더라도 모두가 이것을 지적하는 이유는 상당한 경우에 동등한 부차적 단계가 실제로 존재하며, 그것들을 찾는 것이 문제를 해결하는 첫 번째 단계이기 때문입니다.

를 사용할 try/except제어 흐름에 대해서는 다음과 같이 자문해 보십시오.

  1. 언제인지 쉽게 알 수 있습니까?try블록이 성공하고 실패할 때?
  2. 당신은 내부의 모든 부작용을 알고 있습니까?try 록블?
  3. 당신은 모든 경우에 대해 알고 있습니까?try블록이 예외를 던집니까?
  4. 만약에 그 구현이try변경을 차단합니다. 제어 흐름이 여전히 예상대로 작동합니까?

만약 이 질문들 중 하나 이상에 대한 답이 '아니오'라면, 아마도 여러분의 미래의 자신으로부터 많은 용서를 구할 수 있을 것입니다.


예를 들면.저는 최근에 다음과 같은 더 큰 프로젝트에서 코드를 보았습니다.

try:
    y = foo(x)
except ProgrammingError:
    y = bar(x)

프로그래머와 이야기를 나누면서 의도된 제어 흐름은 다음과 같습니다.

x가 정수이면 y = foo(x)를 수행합니다.

x가 정수 목록이면 y = bar(x)를 실행합니다.

은 이은효있었니다습가과것▁because다니▁this 때문에 효과가 있었습니다.foo이면 쿼리가 할 것입니다.x였고 정였를고 던집니다.ProgrammingError한다면x리스트였습니다.

용사를 합니다.try/except여기서 선택하는 것은 좋지 않은 선택:

  1. 예의이름외,,ProgrammingError실제 문제를 누설하지 않습니다.x는 정수가 아닙니다. 이로 인해 진행 상황을 확인하기가 어렵습니다.
  2. ProgrammingError데이터베이스 호출 중에 발생하여 시간을 낭비합니다.만약 그것이 밝혀진다면 상황은 정말 끔찍해질 것입니다.foo예외를 발생시키거나 다른 시스템의 상태를 변경하기 전에 데이터베이스에 기록합니다.
  3. 의 여부는 불분명합니다.ProgrammingError다음과 같은 경우에만 발생합니다.x정수 목록입니다.예를 들어 다음에 오타가 있다고 가정합니다.foo의 데이터베이스 쿼리입니다.이는 또한 문제를 일으킬 수 있습니다.ProgrammingError그 결과는bar(x)이제 다음과 같은 경우에도 호출됩니다.x는 정수입니다.이로 인해 암호화된 예외가 발생하거나 예측할 수 없는 결과가 발생할 수 있습니다.
  4. try/except을 추가합니다.foo가 바뀔 foo우리는 이제 그것이 목록을 어떻게 처리하는지 생각하고 그것이 확실히 해야 합니다.ProgrammingError그리고, 말하자면, 그것이 아닙니다.AttributeError또는 전혀 오류가 없습니다.

일반적인 의미로 Python: 예외에서 IdiomsAnti-Idioms를 읽는 것을 고려할 수 있습니다.

다른 사람들이 언급한 것처럼 특정한 경우에는 다음을 사용해야 합니다.

get(키[, 기본값])

키가 사전에 있는 경우 키 값을 반환하고, 그렇지 않은 경우 기본값을 반환합니다.기본값이 지정되지 않은 경우 기본값은 없음으로 설정되므로 이 메서드는 키 오류를 발생시키지 않습니다.

언급URL : https://stackoverflow.com/questions/7604636/better-to-try-something-and-catch-the-exception-or-test-if-its-possible-first

반응형