PEP 473 – 내장 예외에 구조화된 데이터 추가
- Author:
- Sebastian Kreft <skreft at deezer.com>
- Status:
- Rejected
- Type:
- Standards Track
- Created:
- 29-Mar-2014
- Post-History:
- Resolution:
- Python-Dev message
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
AttributeError, IndexError, KeyError, LookupError, NameError, TypeError, ValueError와 같은 예외는 프로그래머가 디버깅하고 예외가 발생한 원인을 더 잘 이해하는 데 필요한 모든 정보를 제공하지 않습니다. 또한 경우에 따라 메시지 형식이 서로 약간씩 다르기까지 하므로, 도구가 문제를 진단하기 위한 추가 정보를 자동으로 제공하기가 매우 어렵습니다. 전자의 문제를 해결하고 후자를 위한 기반을 마련하기 위해, 이러한 예외가 문제를 일으킨 개체와 영향을 받은 개체를 모두 보유하도록 확장할 것을 제안합니다.
근거
이 PEP가 해결하려는 주요 문제는 현재 오류 메시지가 충분히 표현력이 없고 예외를 해결하는 데 필요한 일부 핵심 정보가 부족하다는 사실입니다. 또한 오류 메시지에 포함된 정보가 항상 동일한 형식인 것은 아니므로, 서드파티 라이브러리가 오류를 자동으로 진단하기가 매우 어렵습니다.
예를 들어 이러한 자동화 도구는 오타를 감지하거나 추가 디버그 정보를 표시하거나 기록할 수 있습니다. 이러한 기능은 테스트를 실행할 때나 장시간 실행되는 애플리케이션에서 특히 유용할 수 있습니다.
이론적으로는 이러한 라이브러리를 만드는 것이 가능하지만, 목표를 달성하려면 해킹에 의존해야 합니다. 그러한 예 중 하나는 python-improved-exceptions [1]은 바이트코드를 수정하여 관심 대상일 가능성이 있는 객체에 대한 참조를 유지하고, 오류 메시지를 파싱하여 타입이나 이름과 같은 정보를 추출합니다. 안타깝게도 이러한 접근 방식은 매우 취약하고 이식성이 없습니다.
유사한 제안 [2]은 ImportError에 구현되었으며, 같은 방식으로 이 아이디어도 지지 [3]를 받았습니다. 또한 거의 10년 전 Guido는 [11]에서 KeyError, AttributeError, NameError, IndexError와 같은 예외에서 영향을 받은 객체에 접근할 수 있는 깔끔한 API를 마련할 것을 요청했습니다. 지난 1년 동안에도 유사한 문제와 제안 아이디어가 작성되었습니다. 다른 문제들도 제기되었지만, 지지를 받았음에도 결국 방치되었습니다. 생성된 문제에 대한 참조를 아래에 나열합니다.
AttributeError: [11], [10], [5], [4], [3]IndexError: [11], [6], [3]KeyError: [11], [7], [3]LookupError: [11]NameError: [11], [10], [3]TypeError: [8]ValueError: [9]
개발을 진전시키고 정보와 논의를 중앙화하기 위해, 이 PEP는 위의 모든 논의와 아이디어를 요약하는 메타 이슈를 목표로 합니다.
예제
IndexError
오류 메시지는 리스트의 길이나 사용된 인덱스를 참조하지 않습니다.
a = [1, 2, 3, 4, 5]
a[5]
IndexError: list index out of range
KeyError
관례상 키는 오류 인자의 첫 번째 요소이지만, 영향을 받은 딕셔너리에 관한 다른 정보(키의 타입, 크기 등)는 없습니다.
b = {'foo': 1}
b['fo']
KeyError: 'fo'
AttributeError
객체의 타입과 문제가 된 속성은 오류 메시지의 일부입니다. 그러나 형식이 서로 다른 경우가 있으며, 정보를 항상 이용할 수 있는 것은 아닙니다. 또한 객체의 타입이 어떤 경우에는 유용하지만, Python의 동적인 특성을 고려하면 객체 자체에 대한 참조가 있는 편이 훨씬 유용합니다. 게다가 타입에 대한 참조는 완전히 수식되어 있지 않으며, 어떤 경우에는 타입이 유용한 정보를 제공하기에는 너무 일반적입니다. 예를 들어 모듈의 속성에 액세스하는 경우가 그렇습니다.
c = object()
c.foo
AttributeError: 'object' object has no attribute 'foo'
import string
string.foo
AttributeError: 'module' object has no attribute 'foo'
a = string.Formatter()
a.foo
AttributeError: 'Formatter' object has no attribute 'foo'
NameError
오류 메시지는 일반적으로 이름을 제공합니다.
foo = 1
fo
NameError: global name 'fo' is not defined
기타 경우
대상 객체가 다른 표현식의 결과인 경우에는 문제를 디버깅하기가 더욱 어렵습니다. 예를 들면 다음과 같습니다.
a[b[c[0]]]
이 문제는 opcode에 오프셋 정보가 아니라 줄 번호 정보만 있다는 사실과도 관련이 있습니다. 이 제안은 이 경우에 도움이 되지만, 오프셋이 있는 것만큼 큰 도움이 되지는 않습니다.
제안
예외 AttributeError, IndexError, KeyError, LookupError, NameError, TypeError, ValueError를 다음 항목으로 확장합니다.
AttributeError: target w, attributeIndexError: target w, key w, index (key의 별칭일 뿐임)KeyError: target w, key wLookupError: target w, key wNameError: name, scope?TypeError: unexpected_typeValueError: unexpected_value w
위첨자 w가 붙은 속성은 메모리 순환을 방지하기 위해 약한 참조 [12]가 되어야 할 수도 있습니다. 그러나 R.이 지적한 것처럼 이는 불필요한 추가 복잡성을 초래할 수 있습니다. David Murray [13]. 내장 타입은 약한 참조를 지원하지 않는다는 점을 고려하면 특히 그렇습니다.
TODO(skreft): 경계 사례의 예를 추가하십시오.
하위 호환성을 유지하기 위해 이러한 새 속성은 선택 사항이며 키워드 전용입니다.
오류를 단지 개선하는 대신 이 정보를 추가하는 것이 제안됩니다. 전자의 방식이라면 새로운 디버깅 프레임워크와 도구를 사용할 수 있고, 향후 지연 생성 메시지로 전환할 수도 있기 때문입니다. 생성된 메시지는 [2]에서 논의되었지만, 현재는 구현되어 있지 않습니다. 생성된 메시지는 리소스를 일부 절약할 뿐만 아니라 메시지를 통일할 수도 있습니다.
이후 표준 라이브러리는 이러한 새 속성을 사용하기 시작하도록 점진적으로 변경됩니다.
잠재적 용도
자동화된 도구는 예를 들어 객체 내부에서 유사한 키를 검색하여 다음과 같이 표시할 수 있습니다.:
a = {'foo': 1}
a['fo']
KeyError: 'fo'. Did you mean 'foo'?
foo = 1
fo
NameError: global name 'fo' is not defined. Did you mean 'foo'?
TestRunner가 표시할 수 있는 출력은 [3]을 참조하십시오.
성능
이 새 속성들을 채우는 데는 이미 사용 가능한 데이터로 단 두 개의 추가 매개변수만 필요하므로 그 영향은 미미할 것입니다. 그러나 다음 패턴이 이미 널리 퍼져 있으므로 KeyError에 대해서는 특별한 주의가 필요할 수 있습니다.
try:
a[foo] = a[foo] + 1
except:
a[foo] = 0
또한 이 객체들을 오류 자체에 저장하면 [2]에서 논의된 바와 같이 오류 메시지의 지연 생성이 가능해진다는 점에도 유의하십시오.
참고 문헌
Copyright
This document has been placed in the public domain.