0

我試圖將TCP echo client and server用於測試自動化,並將其用於使用ProcessPoolExecutor()的單個模塊,並且按預期工作。Python 3 asyncio:run_until_complete()在等待ProcessPoolExecutor作業完成時阻止

唯一的問題是我無法完成事件循環。我可以看到執行程序目標run_client()的最後一行的調試輸出,但看起來像執行程序本身仍然阻塞。

的代碼:

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

輸出:

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 

此輸出遞給在msg中循環等待IO後。

期待您的幫助。對不起,我是一個天asyncioist :)

回答

0

不能使用相同的事件循環爲您的客戶在一個子運行,你需要一個new loop

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

謝謝你,文森特,爲快速回答。這是確切的解決方案。現在它就像一個魅力與你的額外線路! – ppmag