为什么python async awit 遇到socket.recv阻塞不会切换到其他任务?

image.pngimage.png
想要实现发送与接收的功能,由于存在发送与接收数据1对多的关系,需要做成一边发送,一边循环接收,使用多线程没有用到问题,使用async后如果works中recvData在前,那么就会阻塞在接收,而不会切换到发送,请问这是为什么。

阅读 3.4k
2 个回答

代码太少,不知道你是怎么使用socket的
如果你不用Streams这样的High Level API,
需要eventloop提供的接口,比如
loop.sock_recv(sock, nbytes)

参考
https://docs.python.org/3.7/l...

asyncio 如何处理 读事件 https://segmentfault.com/a/11...

不知道你的 self.recv() 是如何写的,源代码中 create_connection (创建 tcp 连接的方法) 返回的 reader是这样实现的:

    async def _wait_for_data(self, func_name): 
    # 调用通道的 resume_reading 方法,然后等待 数据传输过来(等待 feed_data() or feed_eof() 被调用,self._waiter 就可以结束等待了)
        """Wait until feed_data() or feed_eof() is called.

        If stream was paused, automatically resume it.
        """
        if self._waiter is not None:
            raise RuntimeError(
                f'{func_name}() called while another coroutine is '
                f'already waiting for incoming data')

        assert not self._eof, '_wait_for_data after EOF'

        # Waiting for data while paused will make deadlock, so prevent it.
        # This is essential for readexactly(n) for case when n > self._limit.
        if self._paused:      # 如果现在是暂停状态
            self._paused = False  # 修改为False
            self._transport.resume_reading()  
            # 调用 通道的 resume_reading() 方法恢复读取状态,修改通道的暂停状态,
            # 然后使用 selector (modify 修改已经注册的该通道绑定的 fd )或(register注册该 fd )

        self._waiter = self._loop.create_future()
        try:
            await self._waiter
        finally:
            self._waiter = None

    async def read(self, n=-1):
        ....
        if not self._buffer and not self._eof:  # 如果缓存中没有数据,就等待 _wait_for_data
            await self._wait_for_data('read')
        ...

首先判断缓存区是否有数据,没有的话 就会创建一个 future 挂起,直到 future 得到 result(即有可读事件的fd的事件处理器被调用)。

推荐问题
宣传栏