Klien websocket async Python dengan pengatur waktu async

Saya perlu memiliki klien websocket yang sudah berjalan lama yang menerima pesan push dari server websocket dan saya perlu memantau status koneksi klien: jika koneksi terputus, saya perlu mencari tahu.

Pendekatan saya adalah mencatat string konstan secara berkala, dan memicu alarm jika pesan log tidak terdeteksi.

Ide saya: 1) memiliki klien websocket yang merespons pesan masuk yang tidak teratur. Dan 2) pada saat yang sama memiliki loop yang berhenti mencatat pesan ketika klien websocket mengeluarkan pengecualian ConnectionClosed.

Saya tertarik dengan sintaks async 3.5 yang baru. Implementasi websocket ini secara khusus didasarkan pada asyncio. klien di dokumen terlihat persis seperti yang saya perlukan.

Namun, saya tidak tahu cara menambahkan coroutine kedua yang melakukan pernyataan logging saya dan entah bagaimana berhenti ketika koneksi websocket memunculkan ConnectionClosed.

Ini adalah sesuatu untuk memulai percakapan tetapi itu tidak berhasil karena metode hidup memblokir perulangan peristiwa. Yang saya cari adalah solusi elegan untuk menjalankan kedua metode secara bersamaan.

#!/usr/bin/env python

import asyncio
import logging

import websockets

logger = logging.getLogger(__name__)

is_alive = True


async def alive():
    while is_alive:
        logger.info('alive')
        await asyncio.sleep(300)


async def async_processing():
    async with websockets.connect('ws://localhost:8765') as websocket:
        while True:
            try:
                message = await websocket.recv()
                print(message)

            except websockets.exceptions.ConnectionClosed:
                print('ConnectionClosed')
                is_alive = False
                break


asyncio.get_event_loop().run_until_complete(alive())
asyncio.get_event_loop().run_until_complete(async_processing())

person Dan Schien    schedule 20.02.2016    source sumber


Jawaban (1)


Sebenarnya run_until_complete memblokir di sini, karena menunggu sampai alive selesai.

Anda dapat mengatasinya dengan 2 langkah:

  1. jadwalkan coroutine dengan asyncio.ensure_future (segera berjalan tanpa menunggu hasil ), setiap tugas yang dikembalikan.
  2. tunggu tugas selesai dengan asyncio.wait

Kode seperti:

tasks = [
   asyncio.ensure_future(alive()),
   asyncio.ensure_future(async_processing())
]
asyncio.get_event_loop().run_until_complete(asyncio.wait(tasks))

Seperti yang disebutkan @Vincent wait menerima tugas, jadi ensure_future tidak diperlukan:

asyncio.get_event_loop().run_until_complete(asyncio.wait([   
   alive(),
   async_processing()
]))
person kwarunek    schedule 20.02.2016
comment
Bekerja seperti pesona. Terima kasih banyak. - person Dan Schien; 21.02.2016
comment
Anda dapat meneruskan daftar coroutine ke asyncio.wait, tidak perlu menggunakan asyncio.ensure_future dalam contoh Anda. - person Vincent; 21.02.2016