__await__의 정확한 사양
Python 언어 참조 object.__await__는 다음과 같이 지정 합니다.
object.__await__(self)반복자를 반환해야합니다. 대기 가능한 개체를 구현하는 데 사용해야합니다. 예를 들어,
asyncio.Futureawait 식과 호환되도록이 메서드를 구현합니다.
그게 다야. 이 사양은 매우 모호하고 구체적이지 않습니다 (아이러니하게도). 좋습니다. 반복자를 반환해야하지만 임의의 반복자가 될 수 있습니까? 당연히 아니:
import asyncio
class Spam:
def __await__(self):
yield from range(10)
async def main():
await Spam()
asyncio.run(main())
RuntimeError: Task got bad yield: 0
asyncio이벤트 루프가 반복기에 의해 생성되는 특정 종류의 객체를 기대 한다고 가정하고 있습니다. 그렇다면 정확히 무엇 을 산출해야합니까? (그리고 왜 이것이 문서화되지 않습니까?)
편집 : 내가 볼 수있는 한 이것은 어디에도 문서화되어 있지 않습니다. 그러나 나는 스스로 조사해 왔으며 asyncio코 루틴이 산출 할 것으로 기대 하는 객체를 이해하는 열쇠 task_step_impl는 _asynciomodule.c.
업데이트 : 나는 이것을 명확히하기 위해 cpython 저장소에 PR을 만들었습니다 : "Clarify theobject.__await__ vague specification of " . 현재 검토 중입니다.
답변
언어는 당신이 반환되는 반복자 상관하지 않습니다. 오류는 반복자가 생성해야하는 값의 종류에 대한 특정 아이디어가 있는 라이브러리 asyncio에서 발생합니다. Asyncio는 __await__asyncio 퓨처 (작업과 같은 하위 유형 포함) 또는 None. curio 및 trio와 같은 다른 라이브러리는 다른 종류의 값을 기대합니다. 일반적으로 비동기 라이브러리 __await__는 구현 세부 사항으로 간주하기 때문에 기대치를 문서화하지 않습니다 .
asyncio에 관한 한 퓨처 및 작업과 같은 더 높은 수준의 구성을 사용하고 코 루틴 외에도이를 기다립니다. 이 구현 할 필요는 거의 없습니다 __await__수동으로는, 심지어 다음 다른 awaitable의 신호를 위임하는 데 사용해야합니다. __await__자신의 가치를 생성하고 산출하는 글 을 작성 하려면 이벤트 루프와 결합되고 내부에 대한 지식이 있어야합니다.
__await__asyncio와 유사한 라이브러리를 작성하는 도구로 생각할 수 있습니다 . 그러한 라이브러리의 작성자라면 반복자에서 원하는 것을 생성 할 수 있기 때문에 현재 사양으로 충분하며 이벤트 루프의 코드 만 생성 된 값을 관찰합니다. 그 위치에 있지 않다면 __await__.
작업은 다른 작업 / 미래에만 기다릴 수 있습니다. 로부터 CPython의 소스 코드 :
/* Check if `result` is FutureObj or TaskObj (and not a subclass) */
/* ... */
/* Check if `result` is None */
/* ... error */
/* Check if `result` is a Future-compatible object */
/* ... */
/* Check if `result` is a generator */
/* ... */
/* The `result` is none of the above */
o = task_set_error_soon(
task, PyExc_RuntimeError, "Task got bad yield: %R", result);
Py_DECREF(result);
return o;
편집 :이 제한이 작업에만 부과 __await__된다는 것을 올바르게 이해하고 정상적인 미래는에서 반환 된 모든 이터 러블을 기다릴 수 있습니다.