如何在使用eventlet.monkey_patch()时实现非阻塞的raw_input,为什么它会阻塞一切,尽管在另一个线程中执行?

2 投票
1 回答
4648 浏览
提问于 2025-04-17 11:11

我写了这段简单的代码来说明我的情况:

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)

即使我有两个线程,当我调用 raw_input 时,它们都被阻塞了。当我把 eventlet.monkey_patch() 注释掉时,只有一个线程被阻塞,另一个线程还在不停地打印“printing”。这是为什么呢?我该怎么做?

1 个回答

2

我觉得这里有几点需要注意:

  • raw_input 没有被 eventlet 修改,所以它的调用会阻塞,也就是说在等待输入时会停下来。
  • threadingeventlet 修改了,所以线程的行为就像协程一样。

解决这个问题的一种方法是避免修改 threading,这样线程就会变成真正的线程。要做到这一点,你只需要把:

eventlet.monkey_patch()

替换成:

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

注意,当 thread 设置为 True 时,以下模块会被修改: threadthreadingQueue

补充:如果你想修改 threading 并且让 raw_input 支持异步操作,那么我建议使用以下实现:

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

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

这个实现会检查 sys.stdin 是否准备好读取。如果没有准备好,它会把控制权交给 eventlet,让其他协程执行。

撰写回答