Python asyncio force timeout

前端 未结 3 1654
旧时难觅i
旧时难觅i 2020-12-10 05:17

Using asyncio a coroutine can be executed with a timeout so it gets cancelled after the timeout:

@asyncio.coroutine
def coro():
    yield from asyncio.sleep(         


        
3条回答
  •  Happy的楠姐
    2020-12-10 05:56

    The examples I've seen for timeout handling are very trivial. Given reality, my app is bit more complex. The sequence is:

    1. When a client connects to server, have the server create another connection to internal server
    2. When the internal server connection is ok, wait for the client to send data. Based on this data we may make a query to internal server.
    3. When there is data to send to internal server, send it. Since internal server sometimes doesn't respond fast enough, wrap this request into a timeout.
    4. If the operation times out, collapse all connections to signal the client about error

    To achieve all of the above, while keeping the event loop running, the resulting code contains following code:

    def connection_made(self, transport):
        self.client_lock_coro = self.client_lock.acquire()
        asyncio.ensure_future(self.client_lock_coro).add_done_callback(self._got_client_lock)
    
    def _got_client_lock(self, task):
        task.result() # True at this point, but call there will trigger any exceptions
        coro = self.loop.create_connection(lambda: ClientProtocol(self),
                                               self.connect_info[0], self.connect_info[1])
        asyncio.ensure_future(asyncio.wait_for(coro,
                                               self.client_connect_timeout
                                               )).add_done_callback(self.connected_server)
    
    def connected_server(self, task):
        transport, client_object = task.result()
        self.client_transport = transport
        self.client_lock.release()
    
    def data_received(self, data_in):
        asyncio.ensure_future(self.send_to_real_server(message, self.client_send_timeout))
    
    def send_to_real_server(self, message, timeout=5.0):
        yield from self.client_lock.acquire()
        asyncio.ensure_future(asyncio.wait_for(self._send_to_real_server(message),
                                                       timeout, loop=self.loop)
                                      ).add_done_callback(self.sent_to_real_server)
    
    @asyncio.coroutine
    def _send_to_real_server(self, message):
        self.client_transport.write(message)
    
    def sent_to_real_server(self, task):
        task.result()
        self.client_lock.release()
    

提交回复
热议问题