2015-07-08 20 views
32

PEP 0492 dodaje słowo kluczowe async do Python 3.5.PEP 0492 - Python 3.5 asynchroniczne słowo kluczowe

W jaki sposób Python korzysta z tego operatora? W przykładzie, który jest wobec współprogram jest

async def read_data(db): 
    data = await db.fetch('SELECT ...') 

Według Dokumenty ten osiąga

zawieszenia [ing] wykonanie read_data współprogram aż db.fetch awaitable wypełnia i zwraca dane wynikowe.

Czy to słowo kluczowe async rzeczywiście wiąże się z tworzeniem nowych wątków, czy może z wykorzystaniem istniejącego zastrzeżonego wątku asynchronicznego?

Jeśli w przypadku, gdy async używa zastrzeżonego wątku, czy jest to pojedynczy wątek udostępniony, każdy z osobna?

+1

Wspólne procedury nie używają wątków. –

+3

W tym przypadku, w jaki sposób Python osiąga jakiekolwiek korzyści z zawieszania egzekucji w porównaniu do generatora? –

+4

Należy pamiętać, że PEP ma jedynie na celu ułatwienie kodowania określonych wzorców; nie wprowadzono nowej funkcjonalności ze składnią. Współprocesy * współpracują * w tym sensie, że umożliwiają przełączanie się między zadaniami w predefiniowanych punktach (zamiast wątków, które przełączają wykonanie między różnymi jednostkami w dowolnych punktach). –

Odpowiedz

42

Nie, wspólne procedury nie obejmują żadnych wątków. Współprace pozwalają na wielozadaniowość spółdzielni, ponieważ każda rutynowa kontrola jest dobrowolna. Wątki z drugiej strony przełączają się między jednostkami w dowolnych punktach.

Do wersji Python 3.4, możliwe było pisanie podprogramów przy użyciu generatorów; za pomocą wyrażeń yield lub yield from w ciele funkcji tworzy się obiekt generatora, gdzie kod jest wykonywany tylko podczas iteracji nad generatorem. Razem z dodatkowymi bibliotekami pętli zdarzeń (takimi jak asyncio) można napisać współprogramy, które zasygnalizowałyby pętlę zdarzeń, że będą zajęte (oczekiwanie na I/O) i że może zostać uruchomiona inna rutynowa procedura. tymczasem:

import asyncio 
import datetime 

@asyncio.coroutine 
def display_date(loop): 
    end_time = loop.time() + 5.0 
    while True: 
     print(datetime.datetime.now()) 
     if (loop.time() + 1.0) >= end_time: 
      break 
     yield from asyncio.sleep(1) 

każdym razem powyższy kod przejście do linii yield from asyncio.sleep(1), pętla wydarzenie jest wolny, aby uruchomić inną współpracę rutynę, ponieważ ta procedura nie zrobi nic dla następnego drugiego zresztą.

Ponieważ generator może być stosowany do wszystkich rodzajów zadań, nie tylko współpracownicy rutyny, a ponieważ pisanie współpracy rutynę używając składni generator może być mylące dla nowo przybyłych, PEP wprowadza nową składnię, która sprawia, że ​​jaśniejsze że piszesz rutynę.

z PPG realizowane, powyższe próbki można zapisać jako a nie:

async def display_date(loop): 
    end_time = loop.time() + 5.0 
    while True: 
     print(datetime.datetime.now()) 
     if (loop.time() + 1.0) >= end_time: 
      break 
     await asyncio.sleep(1) 

Otrzymany coroutine obiekt musi jeszcze pętli zdarzeń do napędzania co-procedury; pętla zdarzeń byłaby kolejno await dla każdej z rutynowych procedur, co spowodowałoby wykonanie tych współoperatur, które nie są obecnie await, aby coś mogło się skończyć.

Zaletą jest to, że dzięki natywnej obsłudze można również wprowadzić dodatkową składnię do obsługi asynchronicznych menedżerów kontekstów i iteratorów. Wchodzenie i wychodzenie z menedżera kontekstu lub pętli nad iteratorem może stać się więcej punktów we współrutyny, które sygnalizują, że inny kod może zostać uruchomiony, ponieważ coś czeka ponownie.

+0

Czy jest jakaś przyczyna braku implementacji generatorów asynchronicznych opartych na AsyncInterator jako część wbudowanej składni z wydajnością? –

+0

To jest coś, o czym powinieneś porozmawiać na liście pomysłów Pythona, komentarze SO nie są na to dobrym medium. –

+0

@MartijnPieters Mam trudności ze zrozumieniem asyncio, wciąż. Biorąc pod uwagę twój przykład, wynik jest podobny do '2016-03-04 11: 53: 48.282701' z nową wydrukowaną linią co 1 sekundę. Czy to nie oznacza, że ​​twój program jest zawieszony podczas "oczekiwania"? Spodziewałem się 1-sekundowego opóźnienia po uruchomieniu go, a następnie strumienia drukowanych datetimes, ponieważ 'czekaj asyncio.sleep (...)' powinno ustąpić, gdy tylko zorientuje się, że musi czekać na "io" (w takim przypadku spać). IOW, pętla 'while' będzie nadal działać szybko, a' await's w końcu nadrobić zaległości. Co ja tu nie rozumiem? – orokusaki