0

J'essaie de combiner TCP echo client and server pour tester l'automatisation dans un seul module en utilisant ProcessPoolExecutor() et cela fonctionne comme prévu.Python 3 asyncio: run_until_complete() bloque en attendant le travail ProcessPoolExecutor fait

Le seul problème est que je ne peux pas terminer la boucle d'événements. Je peux voir la sortie de débogage de la dernière ligne de la cible de l'exécuteur run_client(), mais on dirait que l'exécuteur lui-même bloque toujours.

Le code:

import asyncio 
import concurrent.futures 
from concurrent.futures import ProcessPoolExecutor 

async def server_handle_echo(reader, writer): 
    data = await reader.read(100) 
    message = data.decode() 
    addr = writer.get_extra_info('peername') 
    print("Received %r from %r" % (message, addr)) 

    print("Send: %r" % message) 
    writer.write(data) 
    await writer.drain() 

    print("Close the client socket") 
    writer.close() 


async def echo_client_handler(message, loop): 
    reader, writer = await asyncio.open_connection('127.0.0.1', 8888, 
                loop=loop) 

    print('Send: %r' % message) 
    writer.write(message.encode()) 

    data = await reader.read(100) 
    print('Received: %r' % data.decode()) 

    print('Close the socket') 
    writer.close() 



def run_client(): 
    message = 'Hello World!' 
    loop = asyncio.get_event_loop() 
    loop.run_until_complete(echo_client_handler(message, loop)) 
    loop.close() 
    print('run_client last line') 

executor = ProcessPoolExecutor(1) 
loop = asyncio.get_event_loop() 

coro = asyncio.start_server(server_handle_echo, '127.0.0.1', 8888, loop=loop) 
server = loop.run_until_complete(coro) 

# Serve requests until Ctrl+C is pressed 
print('Serving on {}'.format(server.sockets[0].getsockname())) 
try: 
    #loop.run_forever() 
    client = asyncio.ensure_future(loop.run_in_executor(executor, run_client)) 
    loop.run_until_complete(client) 

except KeyboardInterrupt: 
    pass 

# Close the server 
server.close() 
loop.run_until_complete(server.wait_closed()) 
loop.close() 

Sortie:

Serving on ('127.0.0.1', 8888) 
Send: 'Hello World!' 
Received 'Hello World!' from ('127.0.0.1', 51157) 
Send: 'Hello World!' 
Close the client socket 
Received: 'Hello World!' 
Close the socket 
run_client last line 

Après cette sortie, il remet en boucle msg attente pour IO.

Dans l'attente de votre aide. Désolé, je suis un jour asyncioist :)

Répondre

0

Vous ne pouvez pas utiliser la même boucle d'événements pour votre client en cours d'exécution dans un sous-processus, vous avez besoin d'un new loop:

def run_client(): 
    loop = asyncio.new_event_loop() 
    asyncio.set_event_loop(loop) 
    [...] 
+0

Merci, Vincent, pour réponse rapide. C'est la solution exacte. Maintenant, cela fonctionne comme un charme avec vos lignes supplémentaires! – ppmag