ไคลเอ็นต์ Python async websocket พร้อมตัวจับเวลา async

ฉันจำเป็นต้องมีไคลเอนต์ websocket ที่ใช้งานมานานซึ่งได้รับข้อความพุชจากเซิร์ฟเวอร์ websocket และฉันต้องตรวจสอบสถานะการเชื่อมต่อของไคลเอนต์: หากการเชื่อมต่อหยุดทำงาน ฉันจำเป็นต้องค้นหา

วิธีการของฉันคือบันทึกสตริงคงที่เป็นระยะ และส่งสัญญาณแจ้งเตือนหากตรวจไม่พบข้อความบันทึก

ความคิดของฉัน: 1) มีไคลเอนต์ websocket ที่ตอบสนองต่อข้อความขาเข้าที่ผิดปกติ และ 2) ในเวลาเดียวกันมีการวนซ้ำที่หยุดการบันทึกข้อความเมื่อไคลเอนต์ websocket ส่งข้อยกเว้น ConnectionClosed

ฉันรู้สึกทึ่งกับไวยากรณ์ async 3.5 ใหม่ การใช้งาน websocket นี้ ขึ้นอยู่กับ asyncio โดยเฉพาะ ไคลเอนต์ในเอกสารมีลักษณะเหมือนกับที่ฉันต้องการทุกประการ

อย่างไรก็ตาม ฉันไม่รู้ว่าจะเพิ่ม coroutine ตัวที่สองที่คำสั่งการบันทึกของฉัน และ หยุดลงเมื่อการเชื่อมต่อ websocket ส่ง ConnectionClosed ได้อย่างไร

นี่คือสิ่งที่จะเริ่มต้นการสนทนาแต่ไม่ได้ผลเนื่องจากเมธอดที่มีชีวิตจะบล็อกการวนซ้ำของเหตุการณ์ สิ่งที่ฉันกำลังมองหาคือโซลูชันที่ยอดเยี่ยมในการใช้งานทั้งสองวิธีไปพร้อมๆ กัน

#!/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 แหล่งที่มา


คำตอบ (1)


จริงๆ แล้ว run_until_complete กำลังบล็อกอยู่ที่นี่ เนื่องจากจะรอจนกว่า alive จะเสร็จสิ้น

คุณสามารถแก้ไขได้ด้วย 2 ขั้นตอน:

  1. กำหนดเวลา coroutines ด้วย asyncio.ensure_future (ทำงานทันทีโดยไม่ต้องรอผลลัพธ์ ) แต่ละงานที่ส่งคืน
  2. รอให้งานเสร็จสิ้นด้วย asyncio.wait

รหัสเช่น:

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

ตามที่ @Vincent กล่าวถึง wait ยอมรับงาน ดังนั้น ensure_future จึงไม่จำเป็น:

asyncio.get_event_loop().run_until_complete(asyncio.wait([   
   alive(),
   async_processing()
]))
person kwarunek    schedule 20.02.2016
comment
ทำงานเหมือนมีเสน่ห์ ขอบคุณมาก. - person Dan Schien; 21.02.2016
comment
คุณสามารถส่งรายการ coroutines ไปที่ asyncio.wait ได้ โดยไม่จำเป็นต้องใช้ asyncio.ensure_future ในตัวอย่างของคุณ - person Vincent; 21.02.2016