tutorial run gather espaƱol asyncio async python python-3.x pygame python-asyncio

run - import async python



E/S sin bloqueo con asyncio (3)

Estoy tratando de escribir un juego en red con Pygame y asyncio, pero no puedo averiguar cómo evitar colgar en las lecturas. Aquí está mi código para el cliente:

@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()

Esto cuelga en la línea line = yield from reader.read(2**12) . Anteriormente pensé que el punto de asyncio era que no era de bloqueo, por lo que si no hubiera datos para leer, simplemente continuaría ejecutándose. Ahora veo que este no es el caso.

¿Cómo integro el código de red de asyncio con el código de evento y dibujo de Pygame?


Bueno, ya que está intentando leer el valor de ''línea'' justo después de llamar a read (), necesita ese valor a cualquier costo ...

si la rutina no se detendría porque no hay datos, podría obtener un AttributeError en la llamada line.decode () si ''line'' es None.

una cosa que puede hacer es establecer un tiempo de espera en la llamada de bloqueo y manejar la excepción de tiempo de espera:

... print("Waiting to read") try: # block at most for one second line = yield from asyncio.wait_for(reader.read(2**12), 1) except asyncio.TimeoutError: continue else: print(line.decode()) ...


El punto de yield from es cambiar la ejecución al bucle de eventos de asyncio y bloquear la rutina actual hasta que el resultado esté disponible. Para programar una tarea sin bloquear la rutina actual, puede usar asyncio.async() .

Para imprimir datos de lectura hasta el momento sin bloquear el bucle de pygame:

@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

No debe haber llamadas de bloqueo dentro del bucle while.

read() y sleep() coroutines se ejecutan simultáneamente en el mismo hilo (obviamente, también se pueden ejecutar otras coroutines al mismo tiempo).


Puede "transformar" una tarea de bloqueo en una no-bloqueo.

Sugiero esto: https://docs.python.org/3/library/asyncio-eventloop.html#executor .

Tengo una función que escucha un feed de Twitter, la función "mención", y la ejecuto en un ejecutor, por lo que si se bloquea, no bloquea las otras tareas.

@asyncio.coroutine def boucle_deux(): #faire attendre la boucle si pas bcp de mots while True: print("debut du deux") value = t.next() future2 = loop.run_in_executor(None, mention, "LQNyL2xvt9OQMvje7jryaHkN8", "IRJX6S17K44t8oiVGCjrj6XCVKqGSX9ClfpGpfC467rajqePGb", "2693346740-km3Ufby8r9BbYpyzcqwiHhss22h4YkmnPN4LnLM", "53R8GAAncFJ1aHA1yJe1OICfjqUbqwcMR38wSqvbzsQMB", 23, value) response2 = yield from future2 yield from asyncio.sleep(5) print("fin du deux") asyncio.Task(boucle_deux())