Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

PEP 760 – 베어 Except 금지

Author:
Pablo Galindo Salgado <pablogsal at python.org>, Brett Cannon <brett at python.org>
Status:
Withdrawn
Type:
Standards Track
Created:
02-Oct-2024
Python-Version:
3.14
Post-History:
09-Oct-2024

Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain or CC0-1.0, whichever is more permissive 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

초록

이 PEP는 Python의 예외 처리 구문에서 베어 except: 절을 금지할 것을 제안합니다. 현재 Python에서는 베어 except: 절을 사용하여 모든 예외를 포착할 수 있지만, 이로 인해 지나치게 광범위한 예외 처리가 이루어지고 중요한 오류가 가려질 수 있습니다. 이 PEP는 모든 except 절에 명시적인 예외 형식을 요구하여 더 정확하고 의도적인 오류 처리를 장려할 것을 제안합니다.

동기

현재 구문에서는 베어 except: 절을 사용하여 모든 예외를 포착할 수 있습니다.

try:
    risky_operation()
except:
    handle_any_error()

이 구문은 모든 것을 포착하는 처리기에 편리할 수 있지만, 흔히 좋지 않은 코딩 관행으로 이어집니다.

  1. 전파되어야 하는 중요한 오류를 가릴 수 있습니다.
  2. 예기치 않은 예외를 포착하고 잠재적으로 숨기므로 디버깅이 더 어려워집니다.
  3. 이는 암묵적인 것보다 명시적인 것을 중시하는 Python의 원칙에 어긋납니다.

다양한 린터 [1] [2] [3] 및 스타일 가이드(PEP 8 포함) [4] [5] [6] [7]에서는 베어 except 절의 사용을 권장하지 않습니다.

명시적인 예외 형식을 요구하면 더욱 신중하고 정확한 오류 처리를 장려할 수 있습니다.

try:
    risky_operation()
except Exception as e:
    handle_expected_error(e)

이 문제를 다르게 보면, 베어 except 처리기는 종료 예외를 어떻게 처리하려는지에 관해 모호합니다. 의도는 다음 두 가지 중 하나였을 수 있기 때문입니다.

  • 비종료 예외만 포착합니다(except Exception:). 이것이 의도였다면 베어 except:를 사용하는 것은 명백한 버그입니다. 해당 구문이 그런 의미가 아니기 때문입니다.
  • 종료 예외를 포함한 모든 예외를 포착합니다(except BaseException:). 여기서 베어 except:를 사용하는 것은 적어도 올바르지만, 독자는 첫 번째 경우에 해당하지 않는지 확인해야 합니다.

가능한 두 의도 모두 모호하지 않은 표기를 사용할 수 있으므로, 모호한 형식은 중복됩니다. 따라서 이를 금지할 것을 제안합니다.

근거

베어 except 절을 금지하기로 한 결정은 다음 고려 사항에 기반합니다.

  1. 구체적인 예외 형식을 요구하면 프로그래머의 의도가 명확해지고 어떤 예외가 발생할 수 있는지 생각하도록 장려합니다.
  2. 특정 예외만 포착하면 예기치 않은 오류를 식별하고 디버깅하기가 쉬워집니다.
  3. 지나치게 광범위한 예외 처리를 방지하면 중요한 오류를 조용히 무시할 위험이 줄어듭니다.
  4. 많은 스타일 가이드와 린터에서는 이미 베어 except 절의 사용을 권장하지 않습니다.

명세

except 절의 구문은 예외 형식을 요구하도록 수정됩니다. except 절에 빈 표현식을 추가할 수 없도록 문법이 업데이트됩니다.

이 변경으로 베어 except: 구문이 금지됩니다. 모든 except 절은 하나 이상의 예외 형식을 지정해야 합니다.

try:
    ...
except ValueError:
    ...
except (TypeError, RuntimeError):
    ...
except Exception:
    ...  # Still allowed, but catches all exceptions explicitly

예외 처리의 의미는 변경되지 않지만, 이제 BaseException 또는 이와 유사하게 광범위한 예외 형식을 명시하지 않고 모든 예외를 포착할 수는 없습니다.

하위 호환성

이 변경 사항은 하위 호환성이 없습니다. bare except:절을 사용하는 기존 코드는 수정해야 합니다. 전환을 쉽게 하기 위해 다음을 제공합니다.

  1. Python 3.14에서는 bare except 절에 대한 사용 중단 경고가 발행됩니다.
  2. Python 3.17에서는 이 구문이 완전히 금지됩니다.
  3. 이전 버전의 Python에서 bare except 핸들러를 무효화할 수 있도록 from __future__ import strict_excepts문이 제공됩니다.

except:except BaseException:로 자동으로 바꾸도록 코드를 업데이트하는 도구가 제공됩니다.

보안 관련 사항

이 변경 사항은 보안과 관련된 영향이 없습니다.

이 내용을 가르치는 방법

새로운 Python 사용자에게는 처음부터 명시적인 예외 유형을 사용하여 예외 처리를 가르쳐야 합니다.

try:
    result = risky_operation()
except ValueError:
    handle_value_error()
except TypeError:
    handle_type_error()
except Exception as e:
    handle_unexpected_error(e)

숙련된 사용자에게는 이 변경 사항을 이제 언어에서 강제하는 모범 사례로 소개할 수 있습니다. 다음 사항을 강조해야 합니다.

  1. 가능한 경우 항상 특정 예외를 포착하십시오.
  2. 정말로 예상하지 못한 오류에 대한 최후의 수단으로 except Exception:을 사용하십시오.
  3. 신중하게 고려하지 않고 예외를 절대 무시하지 마십시오.

문서에서는 일반적인 예외 계층과 포착하기에 적절한 예외 유형을 선택하는 방법을 안내해야 합니다.

거부된 아이디어

  • bare except:핸들러의 사용이 올바른 실제 사례가 있습니다. Mailman [8]에서 제기된 예 중 하나는 어떤 예외가 발생하더라도 트랜잭션을 처리하는 것과 관련됩니다.
    @contextmanager
    def transaction():
        """Context manager for ensuring the transaction is complete."""
        try:
            yield
        except:
            config.db.abort()
            raise
        else:
            config.db.commit()
    

    이 코드는 어떤 예외가 발생하더라도 열려 있는 트랜잭션이 중단되도록 보장하며, 성공한 경우에는 트랜잭션이 커밋되도록 보장합니다.

    이와 같은 bare except:핸들러가 올바른 사례가 있기는 하지만, “동기” 절에 제시된 이유로 실제로는 명시적으로 except BaseException:을 사용하는 편이 더 낫다고 생각합니다.