как сделать этот код неблокирующим с помощью Asyncio? - PullRequest
0 голосов
/ 17 мая 2018

Я пытаюсь создать код, который не является блокирующим и который позволяет мне создавать несколько клиентов для выполнения некоторого запроса на сервере. Однако я не могу создать более одного клиента одновременно!

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 голосов
/ 17 мая 2018

Ваша 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) будут работать нормально и иметь то же значение, что и более длинные версии.

...