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

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

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 Ответ

2 голосов
/ 27 января 2012

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

  • 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 для выполнения другой сопрограммы.

...