Asyncio Python:对生产者使用无限循环,并在生产者等待TCP流时让消费者进行处理

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中,并在函数从套接字接收数据等待新数据时让这些语句的过程发生 类中我的主循环的伪代码如下所示:

这是我第一次在这里发帖,如果一切都不完美,我感到非常抱歉

情况如下: 我使用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。首先完成
以便在任一任务完成时恢复运行。