Asyncio Python:对生产者使用无限循环,并在生产者等待TCP流时让消费者进行处理
这是我第一次在这里发帖,如果一切都不完美,我感到非常抱歉 情况如下: 我使用python中的套接字通过TCP连接将一些NMEA语句从客户端发送到服务器 我想避免发送和接收NMEA语句的任何延迟。因此,我希望优先接收来自服务器端的NMEA语句,并使用突发数据之间的时间来处理语句并将其存储在数据库中 因此,我想使用asyncio(Python3.8)将NMEA语句连续添加到asyncio.queue中,并在函数从套接字接收数据等待新数据时让这些语句的过程发生 类中我的主循环的伪代码如下所示:Asyncio Python:对生产者使用无限循环,并在生产者等待TCP流时让消费者进行处理,python,python-3.x,python-asyncio,Python,Python 3.x,Python Asyncio,这是我第一次在这里发帖,如果一切都不完美,我感到非常抱歉 情况如下: 我使用python中的套接字通过TCP连接将一些NMEA语句从客户端发送到服务器 我想避免发送和接收NMEA语句的任何延迟。因此,我希望优先接收来自服务器端的NMEA语句,并使用突发数据之间的时间来处理语句并将其存储在数据库中 因此,我想使用asyncio(Python3.8)将NMEA语句连续添加到asyncio.queue中,并在函数从套接字接收数据等待新数据时让这些语句的过程发生 类中我的主循环的伪代码如下所示:
#Producer
async def _read_comms(self,queue):
""" """
while True:
comm_nmea = await self.DataPort.receive_line_async()
await queue.put(comm_nmea)
#Consumers
async def _process_comms(self,queue):
""" """
while True:
comm_nmea = await queue.get()
data = await self.Parser.parse_comm_nmea(comm_nmea=comm_nmea)
await self._data_to_db(data)
#main
async def receive(self):
""" """
self.Logger.info("Start collecting")
while(True):
queue = asyncio.Queue()
await self._read_comms(queue)
await self._process_comms(queue)
if self.update_rate != 0:
time.sleep(self.update_rate)
我必须说我对asyncio真的很陌生(我是为这个项目而开始的)。
我很确定我在那里做了很多蠢事
这段代码的问题是,我从来没有跳出进程_comms()中的第一个循环。
这是意料之中的,但我正在寻找一个解决方案,我在这里试图做什么
这是一个总结,有两个并发循环使用队列作为缓冲区。一个用来输入队列,另一个用来处理队列。没关系,解决了我的问题 对于可能遇到相同问题的用户: 我用以下方法解决了这个问题:
queue = asyncio.Queue()
await asyncio.gather(self._read_comms(queue),self._process_comms(queue))
对于记录,在这种特定情况下,您可以只执行以下操作:
reader=asyncio.create_task(self.\u read_comms(queue))
(不带wait
),wait self.\u process_comms(queue)
,wait reader
collect
是一个很好的速记(并且优于我的备用代码),但从根本上说,您的问题是,您试图在启动第二个任务之前等待第一个任务,这意味着第一个任务必须在第二个任务启动之前运行到完成(这会导致潜在的巨大队列的建立,如果服务器关闭了连接,将无法处理任何内容)。请注意,在某些情况下(包括本例),您可能希望使用asyncio.wait
或asyncio.as_completed
;如果聚集
有一个永不结束的等待,它也不会结束。\u进程_通信
似乎永远运行(在空队列上阻塞),因此您需要添加一个sentinel值,当连接断开时,\u read\u comms
可以发送该值,以便\u process\u comms
知道要完成,或者您希望使用wait
和asyncio。首先完成
以便在任一任务完成时恢复运行。