簡體   English   中英

asyncio隊列消費者協同程序

[英]asyncio queue consumer coroutine

我有一個asyncio.Protocol子類從服務器接收數據。 我在asyncio.Queue存儲這些數據(每行,因為數據是文本)。

import asyncio

q = asyncio.Queue()

class StreamProtocol(asyncio.Protocol):
    def __init__(self, loop):
        self.loop = loop
        self.transport = None

    def connection_made(self, transport):
        self.transport = transport

    def data_received(self, data):
        for message in data.decode().splitlines():
            yield q.put(message.rstrip())

    def connection_lost(self, exc):
        self.loop.stop()

loop = asyncio.get_event_loop()
coro = loop.create_connection(lambda: StreamProtocol(loop),
                              '127.0.0.1', '42')
loop.run_until_complete(coro)
loop.run_forever()
loop.close()

我想讓另一個協程負責消耗隊列中的數據並進行處理。

  • 這應該是asyncio.Task嗎?
  • 如果隊列變空是因為幾秒鍾沒有收到數據怎么辦? 如何確保我的消費者不會停止( run_until_complete )?
  • 有沒有比使用全局變量更簡潔的方法?

這應該是asyncio.Task嗎?

是的,使用asyncio.ensure_futureloop.create_task創建它。

如果隊列變空是因為幾秒鍾沒有收到數據怎么辦?

只需使用queue.get等待項目可用:

async def consume(queue):
    while True:
        item = await queue.get()
        print(item)

有沒有比使用全局變量更簡潔的方法?

是的,只需將其作為參數傳遞給消費者協程和流協議:

class StreamProtocol(asyncio.Protocol):
    def __init__(self, loop, queue):
        self.loop = loop
        self.queue = queue

    def data_received(self, data):
        for message in data.decode().splitlines():
            self.queue.put_nowait(message.rstrip())

    def connection_lost(self, exc):
        self.loop.stop()

如何確保我的消費者不會停止(run_until_complete)?

連接關閉后,使用queue.join等待隊列為空。


完整示例:

loop = asyncio.get_event_loop()
queue = asyncio.Queue()
# Connection coroutine
factory = lambda: StreamProtocol(loop, queue)
connection = loop.create_connection(factory, '127.0.0.1', '42')
# Consumer task
consumer = asyncio.ensure_future(consume(queue))
# Set up connection
loop.run_until_complete(connection)
# Wait until the connection is closed
loop.run_forever()
# Wait until the queue is empty
loop.run_until_complete(queue.join())
# Cancel the consumer
consumer.cancel()
# Let the consumer terminate
loop.run_until_complete(consumer)
# Close the loop
loop.close()

或者,您也可以使用

async def tcp_client(host, port, loop=None):
    reader, writer = await asyncio.open_connection(host, port, loop=loop)
    async for line in reader:
        print(line.rstrip())
    writer.close()

loop = asyncio.get_event_loop()
loop.run_until_complete(tcp_client('127.0.0.1', 42, loop))
loop.close()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM