Python 3 异步 : run_until_complete() blocks when waiting for ProcessPoolExecutor job done

标签 python linux python-3.5 python-multiprocessing python-asyncio

我正在尝试合并 TCP echo client and server使用 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

在此输出之后,它会进入等待 IO 的消息循环。

期待您的帮助。抱歉,我是一日异步主义者 :)

最佳答案

您不能为在子进程中运行的客户端使用相同的事件循环,您需要 new loop :

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

关于Python 3 异步 : run_until_complete() blocks when waiting for ProcessPoolExecutor job done,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45303040/

相关文章:

python - 获取具有不同子列表数据类型的列表元素的交集

Python (3.5) - urllib.request.urlopen - 进度条可用吗?

python - 如何将带有值和表名的参数化语句传递给 Psycopg2?

python - 如何让 Flask 记录到 stdout 而不是 stderr?

python - 如何在 `FormView.get_success_url()`中访问表单数据

linux - shell:从具有已知键的字符串中提取键值

python - 避免多个 IF 以确保 Mccabe 复杂性

linux - 在网络之间设置 Linux 路由表

linux - Vagrant + Composer + Windows/nfs/git 错误

python - 子进程权限被拒绝