2

I'm playing with asyncio UDP server example and would like to have a sleep from within the datagram_received method.

import asyncio

class EchoServerProtocol:
    def connection_made(self, transport):
        self.transport = transport

    def datagram_received(self, data, addr):
        message = data.decode()
        print('Received %r from %s' % (message, addr))
        # Sleep
        await asyncio.sleep(1)
        print('Send %r to %s' % (message, addr))
        self.transport.sendto(data, addr)

loop = asyncio.get_event_loop()
print("Starting UDP server")
# One protocol instance will be created to serve all client requests
listen = loop.create_datagram_endpoint(EchoServerProtocol,
                                       local_addr=('127.0.0.1', 9999))
transport, protocol = loop.run_until_complete(listen)

try:
    loop.run_forever()
except KeyboardInterrupt:
    pass

transport.close()
loop.close()

This fails with a SyntaxError on the sleep line (Python 3.5.1). Using time.sleep is obviously not working as it prevents any other datagram to be received. Any hints on how to solve this?

The goal is to replace this sleep with a real non-blocking I/O call.

greut
  • 4,305
  • 1
  • 30
  • 49

1 Answers1

2

It seems that the await has to live in an async def (coroutine). To do so, you must fire a call via asyncio.ensure_future.

def datagram_received(self, data, addr):
    asyncio.ensure_future(self.reply(data, addr))

async def reply(self, data, addr):
    await asyncio.sleep(1)
    self.transport.sendto(data, addr)
greut
  • 4,305
  • 1
  • 30
  • 49
  • Keep in mind that `ensure_future` only schedules the execution. You do not have guarantee when/how (with error) it will complete if ever. – kwarunek Mar 29 '16 at 20:31