Asyncio dan loop tak terbatas

@asyncio.coroutine
    def listener():
        while True:
            message = yield from websocket.recieve_message()
            if message:
                yield from handle(message)

loop = asyncio.get_event_loop()
loop.run_until_complete(listener())

Katakanlah saya menggunakan websockets dengan asyncio. Itu berarti saya menerima pesan dari websockets. Dan ketika saya menerima pesan, saya ingin menangani pesan tersebut tetapi saya kehilangan semua hal asinkron dengan kode saya. Karena yield from handle(message) jelas memblokir... Bagaimana saya bisa menemukan cara untuk menjadikannya non-pemblokiran? Misalnya, menangani banyak pesan dalam waktu bersamaan. Tidak harus menunggu pesan ditangani sebelum saya dapat menangani pesan lainnya.

Terima kasih.


person Cookie    schedule 02.12.2015    source sumber
comment
Biasanya Anda memerlukan tugas per websocket untuk membaca, menulis ke websocket dapat dilakukan secara asinkron dari tugas lain. handle mungkin juga merupakan tugas terpisah. Kode Anda tidak lengkap, sehingga tidak mudah untuk mendapatkan apa yang sebenarnya Anda perlukan.   -  person Andrew Svetlov    schedule 02.12.2015
comment
jika ini adalah satu-satunya coroutine yang Anda panggil, maka pendengar akan memblokir dalam arti bahwa coroutine akan berjalan tanpa batas (karena perulangan while true). Jika Anda menjalankan coroutine lain secara bersamaan (dengan pernyataan hasil dari pernyataannya sendiri) maka asyncio akan memantul bolak-balik di antara pernyataan hasil dari dan dengan demikian tidak lagi menjadi 'pemblokiran'.   -  person songololo    schedule 02.12.2015


Jawaban (1)


Jika Anda tidak peduli dengan nilai kembalian dari pesan pegangan, Anda cukup membuat Tugas baru untuknya, yang akan berjalan di loop acara bersama pembaca soket web Anda. Berikut ini contoh sederhananya:

@asyncio.coroutine
def listener():
    while True:
        message = yield from websocket.recieve_message()
        if message:
            asyncio.ensure_future(handle(message))

ensure_future akan membuat tugas dan melampirkannya ke loop acara default. Karena loop sudah berjalan, loop tersebut akan diproses bersama pembaca soket web Anda secara paralel. Faktanya, jika itu adalah tugas yang diblokir I/O yang berjalan lambat (seperti mengirim email), Anda dapat dengan mudah menjalankan beberapa lusin tugas penanganan (pesan) sekaligus. Mereka dibuat secara dinamis bila diperlukan, dan dimusnahkan setelah selesai (dengan overhead yang jauh lebih rendah daripada benang pemijahan).

Jika Anda ingin lebih banyak kontrol, Anda cukup menulis ke asyncio.Queue di pembaca dan memiliki kumpulan tugas dengan ukuran tetap yang dapat menggunakan antrian, pola khas dalam pemrograman multi-utas atau multi-proses.

@asyncio.coroutine
def consumer(queue):
    while True:
        message = yield from queue.get()
        yield from handle(message)

@asyncio.coroutine
def listener(queue):
    for i in range(5):
         asyncio.ensure_future(consumer(queue))
    while True:
        message = yield from websocket.recieve_message()
        if message:
            yield from q.put(message)

q = asyncio.Queue()
loop = asyncio.get_event_loop()
loop.run_until_complete(listener(q))
person Ethan Frey    schedule 02.02.2016