PEP 310 – 신뢰할 수 있는 획득/해제 쌍
- Author:
- Michael Hudson <mwh at python.net>, Paul Moore <p.f.moore at gmail.com>
- Status:
- Rejected
- Type:
- Standards Track
- Created:
- 18-Dec-2002
- Python-Version:
- 2.4
- Post-History:
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
입력량이 적은 방식으로 작성할 수 있다면 좋겠습니다:
the_lock.acquire()
try:
....
finally:
the_lock.release()
이 PEP는 앞서 설명한 내용을 일반화하는 구문(‘with’ 블록)과 “small-i” 인터페이스를 제안합니다.
결정
이 PEP는 PEP 343을 채택함에 따라 거부되었습니다.
근거
Python의 예외 처리 철학이 지닌 장점 중 하나는 “잘못된” 일을 하기가 더 어려워진다는 점입니다(예를 들어 일부 시스템 호출의 반환 값을 확인하지 않는 경우가 그렇습니다). 현재 이는 리소스 정리에는 적용되지 않습니다. 리소스(예를 들어 잠금)의 획득 및 해제를 위한 현재 구문은 다음과 같습니다.:
the_lock.acquire()
try:
....
finally:
the_lock.release()
이 구문은 획득과 해제를 (아마도 큰) 코드 블록으로 분리하므로, 코드가 리소스를 올바르게 관리하는지 “한눈에” 확인하기 어렵습니다. 또 다른 흔한 오류는 “acquire” 호출을 try 블록 안에 작성하는 것이며, 이 경우 acquire가 실패하면 잠금이 잘못 해제됩니다.
기본 구문 및 의미론
‘with’ 문장의 구문은 다음과 같습니다.:
'with' [ var '=' ] expr ':'
suite
이 문장은 다음 문장들의 순서와 동등한 것으로 정의됩니다.:
var = expr
if hasattr(var, "__enter__"):
var.__enter__()
try:
suite
finally:
var.__exit__()
(부적절한 객체를 with: 문에서 사용하면 오류가 발생하도록 __enter__의 경우처럼 __exit__ 메서드의 존재 여부를 확인하지는 않습니다).
변수를 생략하면 이름 없는 객체가 스택에 할당됩니다. 이 경우 스위트에서는 이름 없는 객체에 접근할 수 없습니다.
가능한 확장
기본 구문에 대한 여러 잠재적 확장안이 Python Developers 목록에서 논의되었습니다. 이 PEP에서 제안하는 해결책에는 이러한 확장안이 하나도 포함되지 않습니다. 많은 경우 양쪽의 주장이 거의 대등하게 강력합니다. 이러한 경우 PEP에서는 추가적인 기능이 필요할 때 기존 try 블록을 사용할 수 있다는 이유만으로 항상 단순성을 선택해 왔습니다.
여러 표현식
하나의 ‘with’ 문 안에서 여러 표현식을 허용하자는 제안이 있었습니다. __enter__메서드는 왼쪽에서 오른쪽 순서로 호출되고, __exit__메서드는 오른쪽에서 왼쪽 순서로 호출됩니다. 이렇게 하면 둘 이상의 리소스를 관리할 때 중첩된 ‘with’ 문으로 인해 코드가 오른쪽 여백을 향해 밀려나는 것을 방지할 수 있다는 장점이 있습니다. 이 문제의 해결책은 다른 깊은 중첩의 경우와 같습니다. 코드 일부를 별도의 함수로 분리하면 됩니다. 또한 __exit__메서드 중 하나가 예외를 발생시키면 어떻게 되는지(다른 __exit__메서드도 호출해야 하는지?)라는 문제를 해결해야 합니다.
예외 처리
선택적 __except__ 핸들러를 포함하도록 프로토콜을 확장하자는 제안이 있었습니다. 이 핸들러는 예외가 발생할 때 호출되며, 예외를 처리하거나 다시 발생시킬 수 있습니다. 이 확장의 의미를 정확하고 이해하기 쉽게 정의할 수 있는지는 전혀 분명하지 않습니다. 예를 들어, 예외 핸들러가 정의되어 있으면 동등한 코드가 try ... except ... else이어야 하고, 그렇지 않으면 try ... finally이어야 합니까? 일반적으로 이를 컴파일 시점에 어떻게 결정할 수 있습니까? 대안은 해당 코드가 try ... finally내부의 try ... except로 확장되도록 정의하는 것입니다. 그러나 실제 상황에서는 이것이 올바르게 작동하지 않을 수 있습니다.
예외 처리에 대해 확인된 유일한 사용 사례는 트랜잭션 처리(정상적으로 완료되면 커밋하고, 예외가 발생하면 롤백하는 것)입니다. 이는 기존의 일반적인 try ... except ... else블록으로 처리하는 것만큼이나 쉬울 가능성이 높으므로, 이 PEP에는 예외 핸들러에 대한 지원이 포함되어 있지 않습니다.
구현 참고 사항
with 문과 동등하다고 지정된 코드에는 잠재적인 경쟁 조건이 있습니다. 예를 들어, __enter__ 메서드 호출이 완료된 후 try 블록이 시작되기 전에 KeyboardInterrupt 예외가 발생하면 __exit__ 메서드가 호출되지 않습니다. 이로 인해 리소스 누수나 교착 상태가 발생할 수 있습니다. [XXX Guido는 이런 종류의 경쟁 조건을 중요하게 여기며, 이를 처리할 C 수준의 마법을 작성할 예정이라고 밝혔습니다. ‘with’ 문의 구현은 이를 본떠야 합니다.]
미해결 문제
기존 클래스(예를 들어 파일과 유사한 객체 및 잠금)에 적절한 __enter__ 및 __exit__ 메서드를 추가해야 합니까? 찬성하는 명백한 이유는 편리하다는 점입니다(어댑터가 필요하지 않습니다). 반대하는 주장은 내장 파일에는 이 기능이 있지만 (가령) StringIO에는 없다면, 파일 객체에 “with”를 사용하는 코드를 StringIO 객체에 재사용할 수 없다는 것입니다. 따라서 __exit__ = close는 “파일과 유사한 객체” 프로토콜의 일부가 되며, 사용자 정의 클래스가 이를 지원해야 할 수 있습니다.
__enter__ 훅은 불필요할 수 있습니다. 많은 사용 사례에서는 어댑터 클래스가 필요하며, 그런 경우 __enter__ 훅에서 수행하는 작업은 __init__ 훅에서 수행해도 그만큼 쉽게 처리할 수 있습니다.
객체 수명을 명시적으로 제어하는 방법을 사용할 수 있다면, 기존의 __del__ 훅이 __exit__ 훅의 기능을 대신할 수 있습니다. 이 접근 방식을 지지하는 사람과의 이메일 교환 [1]을 통해 저자 중 한 명은 이것이 올바른 생각이 아니라는 확신을 더욱 갖게 되었습니다…
“with …” 구문의 “즉시 사용 가능한 유용성”을 높이기 위해 “__exit__” 메서드를 “close”라고 부르거나, __exit__ 메서드를 찾지 못한 경우 “close” 메서드를 고려하자는 제안이 있었습니다 [2].
‘with …’ 블록과 제너레이터 사이에는 개념적으로 몇 가지 유사점이 있으며, 이로 인해 for 루프가 with 블록의 기능을 구현할 수 있게 하자는 제안이 나왔습니다 [3]. 일부 측면에서는 깔끔해 보이지만, for 루프는 루프 역할에 충실해야 한다고 생각합니다.
대안 아이디어
IEXEC: Holger Krekel – XML과 유사한 구문을 사용하는 일반화된 접근 방식(발견된 URL 없음…).
Holger는 모니터링되는 블록의 제어 흐름 세부 정보를 전달받는 “실행 모니터”에 대해 훨씬 더 광범위한 아이디어를 갖고 있습니다. 흥미로운 아이디어이기는 하지만, 이러한 아이디어는 언어를 심층적이고 미묘한 방식으로 변경할 수 있으므로 다른 PEP에서 다루어야 합니다.
Smalltalk/Ruby의 익명 블록 스타일 확장은 무엇이든 명백히 이 확장을 포괄합니다.
PEP 319은 같은 영역에 속하지만, python-dev에서 논의되었을 때 지지를 얻지 못했습니다.
하위 호환성
이 PEP는 새로운 키워드를 제안하므로 __future__ 게임을 진행해야 합니다.
도입 비용
언어가 점점 커지고 복잡해지고 있다고 주장하는 사람들에게는 불평할 거리가 하나 더 생깁니다. 가르쳐야 할 것이 하나 더 늘어나는 셈입니다.
이 제안이 유용하려면, 표준 라이브러리와 다른 코드에 있는 많은 파일 유사 클래스와 잠금 유사 클래스에
__exit__ = close
또는 이와 유사한 것을 추가해야 합니다.
미도입 비용
올바른 코드를 작성하는 일은 여전히 잘못된 코드를 작성하는 것보다 더 많은 노력을 필요로 합니다.
참고 자료
여기서 언급할 만한 다양한 python-list와 python-dev 논의가 있습니다.
Copyright
This document has been placed in the public domain.