简体   繁体   English

我可以将列表传递给 asyncio.gather 吗?

[英]Can I pass an list to asyncio.gather?

I am trying to start a bunch (one or more) aioserial instances using an for and asyncio.gather without success.我正在尝试使用forasyncio.gather启动一堆(一个或多个)aioserial 实例,但没有成功。

# -*- coding: utf-8 -*-

import asyncio
import aioserial
from protocol import contactid, ademco

def main():
    #   Loop  Asyncio
    loop = asyncio.get_event_loop()
    centrals = utils.auth()
    #   List of corotines to be executed in paralel
    lst_coro = []
    #   Unpack centrals
    for central in centrals:
        protocol = central['protocol']
        id = central['id']
        name = central['name']
        port = central['port']
        logger = log.create_logging_system(name)
        #   Protocols
        if protocol == 'contactid':
            central = contactid.process
        elif protocol == 'ademco':
            central = ademco.process
        else:
            print(f'Unknown protocol: {central["protocol"]}')
        #  Serial (port ex: ttyUSB0/2400)
        dev = ''.join(['/dev/', *filter(str.isalnum, port.split('/')[0])])
        bps = int(port.split('/')[-1])
        aioserial_instance = aioserial.AioSerial(port=dev, baudrate=bps)
        lst_coro.append(central(aioserial_instance, id, name, logger))
    asyncio.gather(*lst_coro, loop=loop)

if __name__ == '__main__':
    asyncio.run(main())

I based this on the asyncio documentation example and some answers from stack overflow.我基于 asyncio 文档示例和堆栈溢出的一些答案。 But when I try to run it, I just got errors:但是当我尝试运行它时,我得到了错误:

Traceback (most recent call last):
  File "/usr/lib/python3.7/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib/python3.7/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/opt/Serial/serial.py", line 39, in <module>
    asyncio.run(main())
  File "/usr/lib/python3.7/asyncio/runners.py", line 37, in run
    raise ValueError("a coroutine was expected, got {!r}".format(main))
ValueError: a coroutine was expected, got None

I also tried to use a set instead of a list, but nothing really changed.我也尝试使用集合而不是列表,但没有真正改变。 Is there a better way to start a bunch of parallels corotines when you need to use a loop?当您需要使用循环时,是否有更好的方法来启动一堆并行 corotines? Thanks for the attention.感谢您的关注。

Your problem isn't with how you call gather .您的问题不在于您如何调用gather It's with how you define main .这与您定义main的方式有关。 The clue is with the error message线索是错误消息

ValueError: a coroutine was expected, got None

and the last line of code in the traceback before the except is raised以及引发异常之前的回溯中的最后一行代码

asyncio.run(main())

asyncio.run wants an awaitable. asyncio.run想要一个可等待的。 You pass it the return value of main , but main doesn't return anything.您将main的返回值传递给它,但main不返回任何内容。 Rather than adding a return value, though, the fix is to change how you define main .但是,解决方法是更改您定义main的方式,而不是添加返回值。

async def main():

This will turn main from a regular function to a coroutine that can be awaited.这会将main从常规的 function 变为可以等待的coroutine

Edit编辑

Once you've done this, you'll notice that gather doesn't actually seem to do anything.完成此操作后,您会注意到gather实际上似乎没有做任何事情。 You'll need to await it in order for main to wait for everything in lst_coro to complete.您需要等待它,以便main等待lst_coro中的所有内容完成。

await asyncio.gather(*lst_coro)

Unrelated to your error: you shouldn't need to use loop inside main at all.与您的错误无关:您根本不需要在main中使用loop gather 's loop argument was deprecated in 3.8 and will be removed in 3.10. gatherloop参数在 3.8 中已弃用,并将在 3.10 中删除。 Unless you're using an older version of Python, you can remove it and your call to asyncio.get_event_loop .除非您使用的是旧版本的 Python,否则您可以删除它并调用asyncio.get_event_loop

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM