2017-11-21 151 views
5

Mam kod, który wygląda tak:Jak dodać typ adnotacji do asyncio.Task

import asyncio 
from typing import List 

def some_callback(result): 
    print(result) 

async def b() -> List[int]: 
    return [1, 2, 3] 

async def a() -> None: 
    search = asyncio.ensure_future(b()) 
    search.add_done_callback(some_callback) 
    await search 

loop = asyncio.get_event_loop() 
loop.run_until_complete(a()) 
loop.close() 

próbuję dodać typ adnotacji do funkcji some_callback, ale nie można w pełni zrozumieć, motyka do opisywania zmienna result. Czy powinien to być Coroutine? A może Awaitable?

Kiedy używam reveal_type z mypy, wyjście o zmiennej result jest Any.

Wynikiem tego programu jest:

<Task finished coro=<b() done, defined at ____.py:7> result=[1, 2, 3]> 

Jak udokumentować tę funkcję prawidłowo?

Odpowiedz

2

Zazwyczaj można uzyskać podstawowe adnotacji jakiegoś zmiennej z tylko drukowanie to typ:

def some_callback(result): 
    print(type(result)) 

ile będzie to pokazać jakąś wewnętrzną <class '_asyncio.Task'> typ, wygląda jak możemy traktować go jako regularnego asyncio.Task:

def some_callback(result): 
    print(type(result) is asyncio.Task) # True 

Ale jak zauważył, możemy również użyć bardziej abstrakcyjny typ następnie Task jak Awaitable od Task jest (podklasa) Awaitable:

print(issubclass(asyncio.Task, typing.Awaitable)) # True 

Nasz wybór zawężony teraz Task lub jednej z jej klas nadrzędnych jak Awaitable (w tym najbardziej ekstremalnym przypadku - Any który jest klasa nadrzędna dla każdej klasy, a które mypy've proponowanego do Ciebie).

add_done_callback jest Future 's method i zgodnie z dokumentacją otrzyma obiekt przyszłości jako jego parametr. To nie będzie żaden rodzaj Awaitable (jak coroutine), ale tylko Future lub niektóre jego podklasy, takie jak Task.

Jeśli chodzi o wybór adnotacji typu, warto być najbardziej abstrakcyjnym na temat tego, co twoja funkcja może zaakceptować jako argument (działa poprawnie) i najbardziej konkretny, co może zwrócić. Tak więc wybierając między Future i Task wolałbym Future (przy założeniu, że nie będziesz używać Task specyficznych tylko attrs). Zgodnie z tą logiką, ostateczna odpowiedź brzmi:

def some_callback(result: asyncio.Future): 
    print(result) 

To wszystko brzmi trochę complecated i czasochłonne, ale gdy pojawi się pomysł, będziesz mógł wybrać adnotacje o wiele szybciej.