Цикл событий Python не работает с stdin - PullRequest
2 голосов
/ 29 мая 2019

Я пытаюсь разобраться с асинцио питона.Я написал этот фрагмент кода только для демонстрации, чтобы очистить концепцию.

import asyncio
import threading


async def printer(b, a):
    print(b)
    await asyncio.sleep(5)
    print(a)


def loop_runner(loop):
    print('[RUNNING LOOP]')
    loop.run_forever()


if __name__ == '__main__':
    event_loop = asyncio.get_event_loop()
    # run_forever() is blocking. running it from separate thread
    loop_thread = threading.Thread(target=loop_runner, args=(event_loop,))
    loop_thread.start()

    while True:
        before, after = input('Before :'), input('After :')
        event_loop.create_task(printer(before, after))

Я запускаю цикл обработки событий из отдельного потока и пытаюсь создавать задачи в цикле во время выполнения.Но я не могу понять, почему этот код не работает.Он принимает ввод, но затем переходит к следующей итерации, ничего не печатая из функции printer.

Удивительно, но если я не беру вводы из stdin, а просто использую жестко закодированные сообщения, подобные этому

   messages = [('Hello', 'world'), ('Foo', 'bar'), ('Alice', 'Bob')]

    for message in messages:
        before, after = message
        coroutine = printer(f'[ITERATION] {count} [MESSAGE] {before}', f'[ITERATION] {count} [MESSAGE] {after}')
        event_loop.create_task(coroutine)
        count += 1

все просто отлично работает.Вывод

[RUNNING LOOP]
[ITERATION] 0 [MESSAGE] Hello
[ITERATION] 1 [MESSAGE] Foo
[ITERATION] 2 [MESSAGE] Alice
[ITERATION] 0 [MESSAGE] world
[ITERATION] 1 [MESSAGE] bar
[ITERATION] 2 [MESSAGE] Bob

Пожалуйста, помогите мне разобраться в этом поведении с input

1 Ответ

1 голос
/ 29 мая 2019

Вы неправильно используете asyncio в первой настройке. Вам не нужно вставлять его в модуль потоков.

Моя рекомендуемая настройка для этого заключается в создании асинхронной функции main, которая содержит бесконечный цикл, в котором вы запрашиваете ввод и создаете задачи. Затем вы можете запустить main из цикла событий после того, как объявите его.

Имейте в виду, ожидание задач, которые вы создаете внутри main в вышеприведенной настройке, необязательно; Так как stdout гарантированно синхронизируется ядром (я уверен, что это правда на 70%), вы можете выполнять столько задач, сколько хотите, за один раз, используя printer (). Однако, если вы ожидаете выполнения заданий, ваша программа не будет распечатываться, пока пользователь пытается ввести данные; он будет вызывать printer (), который сначала записывает в stdout, и запрашивает следующий набор ввода только после завершения printer ().

Надеюсь, что ответит на ваш вопрос. См. Ниже документацию в качестве дополнительного ресурса.

https://docs.python.org/3/library/asyncio-task.html

...