__await__의 정확한 사양

Sep 18 2020

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 " . 현재 검토 중입니다.

답변

7 user4815162342 Sep 19 2020 at 07:15

언어는 당신이 반환되는 반복자 상관하지 않습니다. 오류는 반복자가 생성해야하는 값의 종류에 대한 특정 아이디어가 있는 라이브러리 asyncio에서 발생합니다. Asyncio는 __await__asyncio 퓨처 (작업과 같은 하위 유형 포함) 또는 None. curio 및 trio와 같은 다른 라이브러리는 다른 종류의 값을 기대합니다. 일반적으로 비동기 라이브러리 __await__는 구현 세부 사항으로 간주하기 때문에 기대치를 문서화하지 않습니다 .

asyncio에 관한 한 퓨처 및 작업과 같은 더 높은 수준의 구성을 사용하고 코 루틴 외에도이를 기다립니다. 이 구현 할 필요는 거의 없습니다 __await__수동으로는, 심지어 다음 다른 awaitable의 신호를 위임하는 데 사용해야합니다. __await__자신의 가치를 생성하고 산출하는 글 을 작성 하려면 이벤트 루프와 결합되고 내부에 대한 지식이 있어야합니다.

__await__asyncio와 유사한 라이브러리를 작성하는 도구로 생각할 수 있습니다 . 그러한 라이브러리의 작성자라면 반복자에서 원하는 것을 생성 할 수 있기 때문에 현재 사양으로 충분하며 이벤트 루프의 코드 만 생성 된 값을 관찰합니다. 그 위치에 있지 않다면 __await__.

1 uanirudhx Sep 19 2020 at 02:16

작업은 다른 작업 / 미래에만 기다릴 수 있습니다. 로부터 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__된다는 것을 올바르게 이해하고 정상적인 미래는에서 반환 된 모든 이터 러블을 기다릴 수 있습니다.