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

Python 개선 제안 한국어 번역

PEP 288 – 제너레이터의 속성과 예외

Author:
Raymond Hettinger <python at rcn.com>
Status:
Withdrawn
Type:
Standards Track
Created:
21-Mar-2002
Python-Version:
2.5
Post-History:


Table of Contents

번역·라이선스 안내

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

초록

이 PEP는 실행 중인 제너레이터에 예외를 발생시키고 데이터를 공유하는 메커니즘을 제공하여 제너레이터를 개선하는 것을 제안합니다.

상태

이 PEP는 철회되었습니다. 예외 발생 메커니즘은 확장되어 PEP 343에 흡수되었습니다. 속성 전달 기능은 지지자를 얻지 못했고, 명확한 구현이 없었으며, 실행 중인 제너레이터가 자기 자신의 네임스페이스에 접근할 수 있는 깔끔한 방법도 없었습니다.

근거

현재는 클래스 기반 이터레이터만이 속성과 예외 처리를 제공할 수 있습니다. 그러나 클래스 기반 이터레이터는 작성하기 더 어렵고, 덜 간결하며, 가독성이 떨어지고, 더 느립니다. 더 나은 해결책은 이러한 기능을 제너레이터에도 사용할 수 있게 하는 것입니다.

속성 할당을 가능하게 하면 실행 중인 제너레이터와의 사이에 데이터를 주고받을 수 있게 됩니다. 속성을 사용하여 데이터를 공유하는 접근 방식은 파이썬 전반에 퍼져 있습니다. 다른 접근 방식도 존재하지만, 비교하면 다소 임시방편적입니다.

또 다른 진화 단계는 제너레이터에 예외를 전달할 수 있도록 제너레이터 메서드를 추가하는 것입니다. 현재는 제너레이터 외부에서 예외를 유발하는 깔끔한 방법이 없습니다. 또한, 제너레이터 예외 전달은 제너레이터에 대한 try/finally 금지를 완화하는 데 도움이 됩니다. 이러한 필요성은 종료 시 버퍼를 비우거나 리소스를 닫아야 하는 제너레이터에서 특히 절실합니다.

두 제안 모두 하위 호환성을 갖추고 있으며 새로운 키워드를 필요로 하지 않습니다. 이 제안들은 파이썬 2.5 버전에 권장되고 있습니다.

제너레이터 속성에 대한 명세

본질적으로, 이 제안은 클래스의 속성 쓰기를 흉내 내는 것입니다. 유일한 걸림돌은 제너레이터가 자기 자신의 인스턴스를 참조할 방법이 없다는 것입니다. 그래서 이 제안은 그 참조를 알아낼 수 있는 함수를 제공하는 것입니다. 예를 들면:

def mygen(filename):
    self = sys.get_generator()
    myfile = open(filename)
    for line in myfile:
        if len(line) < 10:
            continue
        self.pos = myfile.tell()
        yield line.upper()

g = mygen('sample.txt')
line1 = g.next()
print 'Position', g.pos

제너레이터 속성의 용도는 다음을 포함합니다:

  1. 제너레이터 클라이언트에게 추가 정보를 제공(위에서 보인 것처럼).
  2. 제너레이터 동작을 제어하는 플래그를 외부에서 설정(데이터 그룹을 언제 단계별로 진입하거나 건너뛸지 제너레이터에 알려주는 것 등).
  3. 복잡한 실행 상태를 가진 지연 소비자를 작성(예를 들어 산술 인코더 출력 스트림).
  4. 코루틴을 작성(Mertz 박사의 글 [1]에서 보여준 것처럼).

이 제안으로 ‘yield’와 ‘next’의 제어 흐름은 변경되지 않습니다. 유일한 변경 사항은 데이터를 제너레이터로, 그리고 제너레이터로부터 전달할 수 있다는 것입니다. 기반이 되는 메커니즘은 대부분 이미 갖춰져 있으며, 접근 함수만 추가하면 됩니다.

제너레이터 예외 전달을 위한 명세

제너레이터 인터페이스에 .throw(exception) 메서드를 추가합니다:

def logger():
    start = time.time()
    log = []
    try:
        while True:
            log.append(time.time() - start)
            yield log[-1]
    except WriteLog:
        writelog(log)

g = logger()
for i in [10,20,40,80,160]:
    testsuite(i)
    g.next()
g.throw(WriteLog)

제너레이터 내부에서 예외를 발생시키기 위한 기존의 우회 방법은 존재하지 않습니다. 이는 Python에서 활성 코드에 예외를 전달하거나 통과시킬 수 없는 유일한 경우입니다.

제너레이터 예외 전달은 또한 제너레이터의 근본적인 한계, 즉 정리 코드를 실행하기 위해 try/finally를 사용할 수 없다는 제약(PEP 255)을 해결하는 데도 도움이 됩니다.

참고 A: throw 메서드의 이름은 여러 이유로 선택되었습니다. Raise는 키워드이므로 메서드 이름으로 사용할 수 없습니다. 현재 실행 지점에서 즉시 예외를 발생시키는 raise와 달리, throw는 먼저 제너레이터로 되돌아간 다음 예외를 발생시킵니다. throw라는 단어는 예외를 다른 위치에 두는 것을 암시합니다. throw라는 단어는 다른 언어에서도 이미 예외와 연관되어 있습니다.

resolve(), signal(), genraise(), raiseinto(), flush()와 같은 대체 메서드 이름도 고려되었습니다. 이 중 어느 것도 throw()만큼 적합하지 않았습니다.

참고 B: throw() 구문을 단순하게 유지하기 위해 raise 구문의 인스턴스 버전만 지원하도록 했습니다(”raise string”이나 “raise class, instance” 변형은 지원하지 않습니다).

g.throw(instance)를 호출하는 것은 가장 최근의 yield 바로 다음에 raise instance를 작성하는 것에 해당합니다.

참고 자료