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
번역·라이선스 안내
이 비공식 한국어 번역은 원문 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()
이 구문은 모든 것을 포착하는 처리기에 편리할 수 있지만, 흔히 좋지 않은 코딩 관행으로 이어집니다.
- 전파되어야 하는 중요한 오류를 가릴 수 있습니다.
- 예기치 않은 예외를 포착하고 잠재적으로 숨기므로 디버깅이 더 어려워집니다.
- 이는 암묵적인 것보다 명시적인 것을 중시하는 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 절을 금지하기로 한 결정은 다음 고려 사항에 기반합니다.
- 구체적인 예외 형식을 요구하면 프로그래머의 의도가 명확해지고 어떤 예외가 발생할 수 있는지 생각하도록 장려합니다.
- 특정 예외만 포착하면 예기치 않은 오류를 식별하고 디버깅하기가 쉬워집니다.
- 지나치게 광범위한 예외 처리를 방지하면 중요한 오류를 조용히 무시할 위험이 줄어듭니다.
- 많은 스타일 가이드와 린터에서는 이미 베어 except 절의 사용을 권장하지 않습니다.
명세
except 절의 구문은 예외 형식을 요구하도록 수정됩니다. except 절에 빈 표현식을 추가할 수 없도록 문법이 업데이트됩니다.
이 변경으로 베어 except: 구문이 금지됩니다. 모든 except 절은 하나 이상의 예외 형식을 지정해야 합니다.
try:
...
except ValueError:
...
except (TypeError, RuntimeError):
...
except Exception:
... # Still allowed, but catches all exceptions explicitly
예외 처리의 의미는 변경되지 않지만, 이제 BaseException 또는 이와 유사하게 광범위한 예외 형식을 명시하지 않고 모든 예외를 포착할 수는 없습니다.
하위 호환성
이 변경 사항은 하위 호환성이 없습니다. bare except:절을 사용하는 기존 코드는 수정해야 합니다. 전환을 쉽게 하기 위해 다음을 제공합니다.
- Python 3.14에서는 bare except 절에 대한 사용 중단 경고가 발행됩니다.
- Python 3.17에서는 이 구문이 완전히 금지됩니다.
- 이전 버전의 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)
숙련된 사용자에게는 이 변경 사항을 이제 언어에서 강제하는 모범 사례로 소개할 수 있습니다. 다음 사항을 강조해야 합니다.
- 가능한 경우 항상 특정 예외를 포착하십시오.
- 정말로 예상하지 못한 오류에 대한 최후의 수단으로
except Exception:을 사용하십시오. - 신중하게 고려하지 않고 예외를 절대 무시하지 마십시오.
문서에서는 일반적인 예외 계층과 포착하기에 적절한 예외 유형을 선택하는 방법을 안내해야 합니다.
거부된 아이디어
- 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:을 사용하는 편이 더 낫다고 생각합니다.
Copyright
This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.