Aktualne informacje:
Począwszy od Pythona 3.7 dodano w tym celu asyncio.create_task(coro)
funkcję wysokiego poziomu .
Powinieneś użyć go zamiast innych sposobów tworzenia zadań z coroutimes. Jeśli jednak chcesz utworzyć zadanie z dowolnego oczekiwanego, powinieneś użyć asyncio.ensure_future(obj)
.
Stare informacje:
ensure_future
vs create_task
ensure_future
Jest to sposób, aby utworzyć Task
z coroutine
. Tworzy zadania na różne sposoby w oparciu o argumenty (w tym użycie create_task
dla programów i obiektów przyszłościowych).
create_task
jest abstrakcyjną metodą AbstractEventLoop
. Różne pętle zdarzeń mogą implementować tę funkcję na różne sposoby.
Do ensure_future
tworzenia zadań należy używać . Będziesz potrzebny create_task
tylko wtedy, gdy zamierzasz zaimplementować własny typ pętli zdarzeń.
Aktualizacja:
@ bj0 wskazał na odpowiedź Guido na ten temat:
Chodzi o ensure_future()
to, że jeśli masz coś, co może być albo coroutine, albo a Future
(ta ostatnia zawiera a, Task
ponieważ jest to podklasa Future
), i chcesz mieć możliwość wywołania metody, która jest zdefiniowana tylko w Future
(prawdopodobnie jedynej przydatnym przykładem jest cancel()
). Kiedy już jest Future
(lub Task
) to nic nie robi; kiedy jest to program, zawija go w plik Task
.
Jeśli wiesz, że masz program i chcesz, aby został on zaplanowany, odpowiednim interfejsem API jest create_task()
. Jedynym momentem, w którym powinieneś wywoływać, ensure_future()
jest dostarczanie API (jak większość własnych interfejsów API asyncio), które akceptuje coroutine lub a Future
i musisz zrobić z nim coś, co wymaga posiadania pliku Future
.
i później:
W końcu nadal uważam, że ensure_future()
jest to odpowiednio mało znana nazwa rzadko potrzebnego elementu funkcjonalności. Tworząc zadanie z programu, należy skorzystać z odpowiednio nazwanego
loop.create_task()
. Może powinien być do tego alias
asyncio.create_task()
?
To dla mnie zaskakujące. Moją główną motywacją do używania przez ensure_future
cały czas było to, że jest to funkcja wyższego poziomu w porównaniu do elementu członkowskiego pętli create_task
(dyskusja zawiera kilka pomysłów, takich jak dodawanie asyncio.spawn
lub asyncio.create_task
).
Mogę również wskazać, że moim zdaniem dość wygodne jest użycie uniwersalnej funkcji, która obsługuje dowolne, Awaitable
a nie tylko programy.
Jednak odpowiedź Guido jest jasna: „Tworząc zadanie z poziomu programu, należy użyć odpowiednio nazwanego loop.create_task()
”
Kiedy programy powinny być opakowane w zadania?
Wrap coroutine in a Task - to sposób na uruchomienie tego programu „w tle”. Oto przykład:
import asyncio
async def msg(text):
await asyncio.sleep(0.1)
print(text)
async def long_operation():
print('long_operation started')
await asyncio.sleep(3)
print('long_operation finished')
async def main():
await msg('first')
task = asyncio.ensure_future(long_operation())
await msg('second')
await task
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Wynik:
first
long_operation started
second
long_operation finished
Możesz zastąpić asyncio.ensure_future(long_operation())
go tylko await long_operation()
po to, aby poczuć różnicę.
create_task
jeśli naprawdę potrzebujesz obiektu zadania, którego normalnie nie potrzebujesz: github.com/python/asyncio/issues/477#issuecomment-268709555