我可以将列表传递给 asyncio.gather 吗?
Can I pass an list to asyncio.gather?
我正在尝试使用 for
和 asyncio.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())
我基于 asyncio documentation 示例和堆栈溢出的一些答案。但是当我尝试 运行 它时,我得到了错误:
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
我也尝试过使用集合而不是列表,但并没有真正改变。当需要使用循环时,有没有更好的方法来启动一堆并行协程?感谢关注
您的问题不在于您如何调用 gather
。这取决于您如何定义 main
。线索是错误消息
ValueError: a coroutine was expected, got None
以及抛出异常之前回溯中的最后一行代码
asyncio.run(main())
asyncio.run
想要等待。您将 main
的 return 值传递给它,但是 main
没有 return 任何东西。不过,解决方法不是添加 return 值,而是更改定义 main
.
的方式
async def main():
这会将 main
从常规函数变为可以等待的 coroutine
。
编辑
完成此操作后,您会注意到 gather
实际上似乎没有执行任何操作。您需要等待它以便 main
等待 lst_coro
中的所有内容完成。
await asyncio.gather(*lst_coro)
与您的错误无关:您根本不需要在 main
中使用 loop
。 gather
的 loop
参数在 3.8 中已弃用,并将在 3.10 中删除。除非您使用的是 Python 的旧版本,否则您可以删除它并调用 asyncio.get_event_loop
.
我正在尝试使用 for
和 asyncio.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())
我基于 asyncio documentation 示例和堆栈溢出的一些答案。但是当我尝试 运行 它时,我得到了错误:
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
我也尝试过使用集合而不是列表,但并没有真正改变。当需要使用循环时,有没有更好的方法来启动一堆并行协程?感谢关注
您的问题不在于您如何调用 gather
。这取决于您如何定义 main
。线索是错误消息
ValueError: a coroutine was expected, got None
以及抛出异常之前回溯中的最后一行代码
asyncio.run(main())
asyncio.run
想要等待。您将 main
的 return 值传递给它,但是 main
没有 return 任何东西。不过,解决方法不是添加 return 值,而是更改定义 main
.
async def main():
这会将 main
从常规函数变为可以等待的 coroutine
。
编辑
完成此操作后,您会注意到 gather
实际上似乎没有执行任何操作。您需要等待它以便 main
等待 lst_coro
中的所有内容完成。
await asyncio.gather(*lst_coro)
与您的错误无关:您根本不需要在 main
中使用 loop
。 gather
的 loop
参数在 3.8 中已弃用,并将在 3.10 中删除。除非您使用的是 Python 的旧版本,否则您可以删除它并调用 asyncio.get_event_loop
.