Я пытаюсь написать небольшой параллельный обработчик потока с помощью Slack RTM API, и мне интересно, является ли это наиболее эффективным использование сопрограмм Python. В пакете asyncio
имеется множество опций, но трудно определить, какой правильный подход для проекта и документация, на мой взгляд, не очень помогают объяснить, какие преимущества/недостатки для каждого.Является ли это предполагаемым шаблоном для использования сопрограмм Python `asyncio`?
Я думаю, что мне не нужно иметь накладные расходы на несколько потоков здесь, и мне нужна связь между асинхронными циклами. Должен ли я создать отдельный BaseEventLoop
для каждой из моих функций?
Будучи Python, я думаю, что есть около -deterministic здесь ответа на этот вопрос (There should be one-- and preferably only one --obvious way to do it
), но я боюсь, что добавление всего это асинхронный хлама может просто сделать мой код меньшей производительности, чем полностью последовательная наивной реализация.
# Is this the best way to communicate between coroutines?
incoming_message_q = asyncio.Queue()
async def print_event():
logging.info("Entering log loop")
# Should this operate within it's own BaseEventLoop?
while True:
event = await incoming_message_q.get()
logging.info(event)
async def log_queue_status():
while True:
logging.info(incoming_message_q.qsize())
await asyncio.sleep(5)
async def read_rtm_connection(client, q):
if client.rtm_connect():
logging.info("Successful Slack RTM connection")
while True:
# How do I make this part non-blocking?
events = client.rtm_read()
for event in events:
logging.info("Putting onto the queue", event)
if event["type"] == "presence_change":
await q.put(event)
elif event["type"] == "message":
await q.put(event)
else:
logging.info("Not sure what to do")
await asyncio.sleep(0.1)
else:
logging.info("RTM connection failed.")
loop = asyncio.get_event_loop()
loop.create_task(print_event())
loop.create_task(log_queue_status())
loop.create_task(read_rtm_connection(client, incoming_message_q))
loop.run_forever()
Я не знаком с Slack или каким-то методом rtm_read(), поэтому с учетом этого: Чтобы сделать что-то неблокирующее, это должна быть ожидаемая сопрограмма, которую вы можете запускать как задачу asyncio, используя security_future() , Если rtm_read() не является сопрограммой coroutine, вы можете попробовать обернуть ее в сопрограмму, которая каким-то образом опросит rtm_read(), чтобы выполнить доставку новых событий и передать их другим методам. В зависимости от вашего случая вы можете передавать сообщения о событиях прямо в очередь или иным образом возвращать будущее каждый раз, когда принимается событие, и использовать внутрипрограммный цикл внутри сопрограммы для их итерации. – shongololo