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-268709555ensure_future
automatycznie dodaje utworzoneTask
do głównej pętli zdarzeń?loop
argumentu słowa kluczowego ( patrz podpis zapewnia_przyszłość ).await
wewnątrz,msg()
aby zwrócić kontrolę do pętli zdarzeń przy drugim wywołaniu. Pętla zdarzeń po odebraniu sterowania będzie mogła się rozpocząćlong_operation()
. Ma to na celu zademonstrowanie, w jaki sposóbensure_future
program uruchamia się równolegle z bieżącym przepływem wykonywania.create_task()
ensure_future()
create_task
,Jak widać, create_task jest bardziej szczegółowe.
async
funkcjonować bez funkcji create_task lub secure_futureProsta
async
funkcja wywołująca zwraca coroutine>>> async def doit(i): ... await asyncio.sleep(3) ... return i >>> doit(4) <coroutine object doit at 0x7f91e8e80ba0>
A ponieważ
gather
pod maską zapewnia (ensure_future
), że argumenty są przyszłością, jawnieensure_future
jest zbędne.Podobne pytanie Jaka jest różnica między loop.create_task, asyncio.async / sure_future i Task?
źródło
Z oficjalnych dokumentów:
Szczegół:
Tak więc teraz, w Pythonie 3.7 i nowszych, istnieją dwie funkcje opakowujące najwyższego poziomu (podobne, ale różne):
asyncio.create_task
: które po prostu zadzwońevent_loop.create_task(coro)
bezpośrednio. ( patrz kod źródłowy )ensure_future
które również wywołują,event_loop.create_task(coro)
jeśli jest to coroutine, lub po prostu zapewniają, że typem zwracanym jest asyncio.Future . ( patrz kod źródłowy ). W każdym razieTask
nadal jestFuture
ze względu na dziedziczenie klas ( ref ).Cóż, ostatecznie obie te funkcje opakowujące pomogą Ci wywołać
BaseEventLoop.create_task
. Jedyna różnica toensure_future
akceptacjaawaitable
obiektu i pomoc w przekształceniu go w przyszłość. Możesz także podać własnyevent_loop
parametr wensure_future
. W zależności od tego, czy potrzebujesz tych możliwości, czy nie, możesz po prostu wybrać, którego opakowania chcesz użyć.źródło
na przykład wszystkie trzy typy są wykonywane asynchronicznie. jedyną różnicą jest to, że w trzecim przykładzie wstępnie wygenerowałeś wszystkie 10 programów i przesłałeś je razem do pętli. więc tylko ostatni daje wyniki losowo.
źródło