Выполнить сопрограмму после запуска сервера asyncio - PullRequest
0 голосов
/ 01 августа 2020

Я работаю над приложением контроллера, которое отслеживает и управляет подпроцессами, которые являются независимыми python исполняемыми файлами. В основном я хочу, чтобы в controller.py работал asyncio.star_server. После того, как сервер будет запущен и запущен, controller.py должен выполнить другие файлы python в качестве клиентов, которые будут подключаться к нему. Сервер контроллера работает вечно и создает новые экземпляры клиентов, а также при необходимости отправляет им сообщение о завершении работы.

К сожалению, это не работает. Ошибка не получена, он просто зависает.

controller.py:


async def handleClient(reader, writer):
    #handling a connection
    addr = writer.get_extra_info("peername")
    print(f"connection from {addr}")

    data_ = await reader.readline()
    ...

async def startClient(client_py_file, host, port):
    # this executes another py file that will connect to this server
    await asyncio.sleep(0.1)
    subprocess.run(["python.exe", client_py_file, host, port])

async def main():
    server = await asyncio.start_server(handleClient, "127.0.0.1", 4000)
    await asyncio.ensure_future(startClient("client.py", "127.0.0.1", 4000)
    await server.wait_closed()

asyncio.run(main())

Кажется, он выполняет запускаемый client.py, который подключается к серверу без любая ошибка.

client.py:

async def async_client(loop):
    reader, writer = await asyncio.open_connection(host, port, loop = loop)
    writer.writelines([json.dumps("key" : idstr, "msg" : "this is my message"}, b"\n"])
    await writer.drain()
    while True:
        data = await reader.readline()
        ....

теперь клиент зависает и ждет ответа от сервера. Но на сервере обработчик handleClient не срабатывает. Понятия не имею, что пошло не так. Не могли бы вы мне помочь? Заранее спасибо!

1 Ответ

1 голос
/ 01 августа 2020

Проблема в том, что subprocess.run - это функция блокировки, которая ожидает, пока клиент завершит sh. Во время этого ожидания событие l oop заблокировано и не может обслуживать входящие соединения.

Самое простое исправление - заменить subprocess.run(...) на subprocess.Popen(...), которое делает то же самое, но возвращает дескриптор для подпроцесс, не дожидаясь его завершения sh. Если вам нужно взаимодействовать с подпроцессом, вы также можете использовать asyncio.create_subprocess_exec(...), который также возвращает дескриптор, но тот, чьи методы, такие как wait(), являются сопрограммами.

...