Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non-blocking I/O with asyncio

Tags:

I'm trying to write a networked game with Pygame and asyncio, but I can't work out how to avoid hanging on reads. Here is my code for the client:

@asyncio.coroutine def handle_client():     print("Connected!")     reader, writer = yield from asyncio.open_connection('localhost', 8000)     while True:         mouse_up = False         for event in pygame.event.get():             if event.type == pygame.QUIT:                 pygame.quit()                 sys.exit()                             elif event.type == pygame.MOUSEBUTTONUP:                 mouse_up = True          if mouse_up:             print("Writing")             writer.write(b"Mouse up")         print("Waiting to read")         line = yield from reader.read(2**12)         print(line.decode())      writer.close() 

This hangs on the line line = yield from reader.read(2**12). I previously thought that the point of asyncio was that it was non-blocking, and so if there wasn't any data to read it would just continue executing. I see now that this isn't the case.

How do I integrate the asyncio networking code with the Pygame drawing and event code?

like image 381
rlms Avatar asked Dec 28 '14 13:12

rlms


People also ask

What is non blocking I O model?

Non-blocking I/O operations allow a single process to serve multiple requests at the same time. Instead of the process being blocked and waiting for I/O operations to complete, the I/O operations are delegated to the system, so that the process can execute the next piece of code.

How does non blocking IO work?

Non-blocking IO under the hood Most non-blocking frameworks use an infinite loop that constantly checks (polls) if data is returned from IO. This is often called the event loop. An event loop is literally a while(true) loop that in each iteration will check if data is ready to read from a network socket.

What is blocking vs non blocking IO?

The difference is obvious from its name — instead of blocking, any operation is executed immediately. Non-blocking I/O means that the request is immediately queued and the function is returned. The actual I/O is then processed at some later point.

Can asynchronous I O still be blocking?

Any task that depends on the I/O having completed (this includes both using the input values and critical operations that claim to assure that a write operation has been completed) still needs to wait for the I/O operation to complete, and thus is still blocked, but other processing that does not have a dependency on ...


1 Answers

The point of yield from is to switch the execution to the asyncio's event loop and to block the current coroutine until the result is available. To schedule a task without blocking the current coroutine, you could use asyncio.async().

To print read-so-far data without blocking the pygame loop:

@asyncio.coroutine def read(reader, callback):     while True:         data = yield from reader.read(2**12)         if not data: # EOF             break         callback(data)  @asyncio.coroutine def echo_client():     reader, ...     chunks = []     asyncio.async(read(reader, chunks.append))     while True:         pygame.event.pump() # advance pygame event loop         ...         if chunks: # print read-so-far data             print(b''.join(chunks).decode())             del chunks[:]         yield from asyncio.sleep(0.016) # advance asyncio loop 

There should be no blocking calls inside the while loop.

read() and sleep() coroutines run concurrently in the same thread (obviously you could run other coroutines concurrently too).

like image 54
jfs Avatar answered Sep 21 '22 15:09

jfs