簡體   English   中英

Asyncio和Rabbitmq(Asynqp):如何從多個隊列中同時使用

[英]Asyncio and rabbitmq (asynqp): how to consume from multiple queues concurrently

我正在嘗試使用python,asyncio和asynqp同時使用多個隊列。

我不明白為什么我的asyncio.sleep()函數調用沒有任何效果。 代碼不會在那里暫停。 公平地說,我實際上不了解在哪個上下文中執行回調,以及我是否完全可以將控件bavck賦予事件循環(這樣asyncio.sleep()調用asyncio.sleep()意義)。

如果必須在process_msg回調函數中使用aiohttp.ClientSession.get()函數調用怎么辦? 我無法執行此操作,因為它不是協程。 必須有一種超出我當前對異步的理解的方法。

#!/usr/bin/env python3

import asyncio
import asynqp


USERS = {'betty', 'bob', 'luis', 'tony'}


def process_msg(msg):
    asyncio.sleep(10)
    print('>> {}'.format(msg.body))
    msg.ack()

async def connect():
    connection = await asynqp.connect(host='dev_queue', virtual_host='asynqp_test')
    channel = await connection.open_channel()
    exchange = await channel.declare_exchange('inboxes', 'direct')

    # we have 10 users. Set up a queue for each of them
    # use different channels to avoid any interference
    # during message consumption, just in case.
    for username in USERS:
        user_channel = await connection.open_channel()
        queue = await user_channel.declare_queue('Inbox_{}'.format(username))
        await queue.bind(exchange, routing_key=username)
        await queue.consume(process_msg)

    # deliver 10 messages to each user
    for username in USERS:
        for msg_idx in range(10):
            msg = asynqp.Message('Msg #{} for {}'.format(msg_idx, username))
            exchange.publish(msg, routing_key=username)


loop = asyncio.get_event_loop()
loop.run_until_complete(connect())
loop.run_forever()

我不明白為什么我的asyncio.sleep()函數調用沒有任何效果。

因為asyncio.sleep()返回一個將來的對象,該對象必須與事件循環(或async/await語義)結合使用。

您不能在簡單的def聲明中使用await ,因為該回調是在async/await上下文外部調用的,該上下文附加到async/await某些事件循環中。 換句話說,將回調樣式與async/await樣式混合起來非常棘手。

不過,簡單的解決方案是將工作安排回事件循環:

async def process_msg(msg):
    await asyncio.sleep(10)
    print('>> {}'.format(msg.body))
    msg.ack()

def _process_msg(msg):
    loop = asyncio.get_event_loop()
    loop.create_task(process_msg(msg))
    # or if loop is always the same one single line is enough
    # asyncio.ensure_future(process_msg(msg))

# some code
await queue.consume(_process_msg)

請注意,在沒有遞歸_process_msg功能,即體內process_msg沒有,而在執行_process_msg 控件返回事件循環后,將調用內部process_msg函數。

可以使用以下代碼對此進行概括:

def async_to_callback(coro):
    def callback(*args, **kwargs):
        asyncio.ensure_future(coro(*args, **kwargs))
    return callback

async def process_msg(msg):
    # the body

# some code
await queue.consume(async_to_callback(process_msg))

有關解決方案,請參見GitHubDrizzt1991的響應

暫無
暫無

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

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