如何使用Asyncio进行此代码非阻止?

时间:2018-05-16 23:14:59

标签: python-3.x asynchronous client python-asyncio nonblocking

我尝试创建一个非阻塞的代码,并允许我创建多个客户端以在服务器上执行某些请求。但是,我不能同时创建多个客户端!

CLIENT.PY

import asyncio

PYTHONASYNCIODEBUG = 1


#ECHO CLIENT PROTOCOL 

async def tcp_echo_client(message, loop):
    # Send request to server
    reader, writer = await asyncio.open_connection('127.0.0.1', 8888, loop=loop)
    print('Send: %r' % message)
    writer.write(message.encode())

    # Receive the information
    if message == '1':
        await asyncio.Task(read_position(reader))
    else:
        await asyncio.ensure_future(read_server(reader))

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


#ASYNCIO COROUTINES TO REQUEST INFORMATION 

async def read_server(reader):
    server_message = await reader.read()
    print(type(server_message))
    print('Received: %r' % server_message.decode())


async def read_position(reader):
    while True:
        print("I'm Here")

        server_message = await reader.read(50)
        position = server_message.split()
        print(position)
        print(type(position))
        print('Received: %r' % server_message.decode())


#FUNCTION THAT CREATES THE CLIENT


def main(message):
    '''This function creates the client'''

    loop = asyncio.get_event_loop()
    try:
        loop.run_until_complete(tcp_echo_client(message, loop))
    finally:
        pass


 # This is how I create a new client

if __name__ == '__main__':
    message = '2'
    main(message)
    message = '3'
    main(message)

我想创建多个客户端,但是,当我发送消息时,代码在第一个主要代码中阻塞(' 1')。如果我使用asyncio,我不知道为什么代码会阻塞。我的服务器接受多个连接,因为如果我单独运行此代码,我可以做任何事情。建议这是每次我点击我的Kivy应用程序的按钮向服务器发送请求时创建客户端。 存在这个问题是因为我想要控制一个机器人并同时做很多事情,但是使用阻止代码我无法做到这一点因为我被卡住了

也许这是一个愚蠢的问题,但我只是在2个月前开始编码,而且我没有任何帮助。

1 个答案:

答案 0 :(得分:0)

您的main函数不会像创建文档字符串一样“创建客户端”。它创建客户端并将其运行至完成。这就是main()的多次调用导致串行执行的原因。 main()是一个常规函数,这正是你所期望的,asyncio不会改变它。记住asyncio是单线程的是有用的,所以它不能做一些“在后台运行”魔术,除非你合作。

要合作,你需要告诉aysncio启动两个客户端,然后并行等待它们:

async def main(messages):
    loop = asyncio.get_event_loop()
    # launch the coroutines in parallel
    tasks = [loop.create_task(tcp_echo_client(msg, loop)) for msg in messages]
    # don't exit until all of them are done
    await asyncio.gather(*tasks)

if __name__ == '__main__':        
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(['2', '3']))

请注意,在等待你的协同程序时,你不需要将它们包装在asyncio.ensure_future()asyncio.Task()中 - asyncio会自动处理它。 await read_position(reader)await read_server(reader)可以很好地工作,并且具有与较长版本相同的含义。