Как сделать неблокирующим raw_input при использовании eventlet.monkey_patch() и почему он блокирует все, даже когда выполняется в другом потоке?

Я написал этот минимальный код, чтобы объяснить мой случай:

import threading
import time
import eventlet

eventlet.monkey_patch()

def printing_function():
    while True:
        # here i want to do some work
        print "printing"
        time.sleep(1)

if __name__ == '__main__':
    thread = threading.Thread(target=printing_function)
    thread.start()

    while True:
        # here i want to wait for users input
        raw_input("raw input\n")
        print "inside main loop"
        time.sleep(1)

Даже у меня есть 2 потока, оба они блокируются, когда я вызываю raw_input. Когда я комментирую eventlet.monkey_patch(), блокируется только один поток, а другой продолжает печатать "печать". Почему и что мне делать?

1 ответ

Решение

Я бы сказал, что здесь нужно отметить пару вещей:

  • raw_input не исправлено eventletпоэтому его звонки блокируются
  • threading залатан eventletпоэтому потоки действуют как сопрограммы

Одним из способов обойти это было бы избежать исправлений threadingтак, чтобы потоки были реальными. Для этого вам просто нужно заменить:

eventlet.monkey_patch()

с:

eventlet.monkey_patch(os=True,
                     select=True,
                     socket=True,
                     thread=False,
                     time=True)

Обратите внимание, что когда thread является True исправлены следующие модули: thread, threading, Queue,

Изменить: если вы хотите патч threading и иметь асинхронный raw_inputЗатем я предлагаю следующую реализацию:

def raw_input(message):
    sys.stdout.write(message)

    select.select([sys.stdin], [], [])
    return sys.stdin.readline()

Это будет опрос sys.stdin проверить, готов ли он к чтению. Если это не так, он даст управление eventlet, чтобы позволить другим сопрограммам исполниться.

Другие вопросы по тегам