8.13. Sterowanie pętlą

Większość skryptów asyncio nigdy nie dotyka bezpośrednio pętli zdarzeń – asyncio.run() wystarcza. Ta strona omawia interfejs Loop dla przypadków, gdy to nie wystarcza: instalowania obsługi wyjątków, uruchamiania pętli z innym cyklem życia niż run lub przechowywania obiektu pętli na potrzeby instrumentacji.

8.13.1. Pobieranie pętli

  • asyncio.get_event_loop() – zwraca obiekt Loop. Można go bezpiecznie wywołać zarówno wewnątrz, jak i na zewnątrz korutyny.

  • asyncio.new_event_loop() – w MicroPython resetuje stan istniejącej pętli, zamiast tworzyć nową. Warto powtórzyć uwagę: w programie istnieje dokładnie jedna pętla zdarzeń.

Nie ma API do uruchamiania pętli innego niż metody klasy Loop oraz asyncio.run().

8.13.2. Bezpośrednie uruchamianie pętli

asyncio.run() to właściwy punkt wejścia dla niemal każdej aplikacji. Dla przypadków, gdy nim nie jest, istnieją dwie metody Loop.

  • run_until_complete() – mając dany obiekt awaitable, uruchamia pętlę do momentu jego zakończenia, a następnie zwraca jego wynik. Odpowiednik pojedynczego wywołania asyncio.run(), z pominięciem zburzenia pętli.

  • run_forever() – uruchamia pętlę, dopóki nie zostanie wywołane stop() z wnętrza zadania. Brak obiektu awaitable najwyższego poziomu; oczekuje się, że aplikacja zaplanuje to, czego potrzebuje, za pomocą asyncio.create_task() przed wywołaniem run_forever.

Metodami towarzyszącymi są stop() (żądanie zatrzymania pętli po zakończeniu bieżącego zadania) oraz close() (zwolnienie zasobów pętli).

8.13.3. Tworzenie zadań po stronie pętli

  • create_task() – ta sama operacja co asyncio.create_task(). Wolna funkcja istnieje, aby kod aplikacji nie potrzebował referencji do pętli w typowym przypadku; metoda istnieje na potrzeby instrumentacji, która już ją posiada.

8.13.4. Obsługa wyjątków

Pętla wywołuje funkcję obsługi, gdy zadanie zgłasza wyjątek, którego nic w łańcuchu wywołań korutyny nie przechwyciło – typowym przypadkiem jest zadanie utworzone przez aplikację za pomocą asyncio.create_task(), na które nigdy nie wykonano await. Domyślna funkcja obsługi wypisuje ślad stosu przez sys.stderr; strona o wyjątkach pokazała, jak podmienić ją na coś niestandardowego.

  • set_exception_handler() – instaluje niestandardową funkcję obsługi. Funkcja obsługi to obiekt wywoływalny handler(loop, context), gdzie context jest słownikiem zawierającym co najmniej 'message', a zazwyczaj również 'exception' i 'future'.

  • get_exception_handler() – zwraca aktualnie zainstalowaną funkcję obsługi lub None, jeśli używana jest domyślna.

  • default_exception_handler() – wbudowana funkcja obsługi. Przydatna wewnątrz niestandardowej funkcji obsługi, która chce również wykonać domyślne zachowanie (na przykład zapisać do pamięci flash oraz wypisać ślad stosu).

  • call_exception_handler() – uruchamia aktualnie zainstalowaną funkcję obsługi z ręcznie zbudowanym słownikiem kontekstu. Używane głównie przez samą pętlę; aplikacja rzadko tego potrzebuje.