多线程环境下调用input()两次后失效问题咨询
多线程中input()调用两次后失效的问题解决
问题复现
你遇到的问题是:在子线程里调用input(),输入两次后无法正常捕获输入,后续输入的内容会被直接输出成aaa [输入内容]的格式,input()拿到的是空值。复现代码和运行结果如下:
代码
import queue import threading queue = queue.Queue(maxsize=5) def t(): while True: i = input() print('aaa',i, queue.qsize()) queue.put(i, block=True) threading.Thread(target=t).start()
运行结果
5 aaa 5 0 5 aaa 5 1 2 aaa 2 3 aaa 3 4 aaa 4 5 aaa 5
问题根源
Python的标准输入(stdin)不是线程安全的。你的代码里,子线程启动后主线程并没有退出,它会在后台等待子线程结束,期间如果有输入,主线程和子线程会争抢stdin的控制权,导致input()无法正确读取输入内容,出现拿到空值的情况。另外,当队列接近满负载时,queue.put()的阻塞也会加剧这种竞争。
解决办法
1. 让主线程处理输入(推荐)
把输入逻辑放在主线程,子线程负责处理队列里的内容,从根源上避免多线程抢stdin:
import queue import threading queue = queue.Queue(maxsize=5) def handle_queue(): while True: item = queue.get() print(f"处理输入: {item}, 队列当前大小: {queue.qsize()}") queue.task_done() # 启动后台处理线程 threading.Thread(target=handle_queue, daemon=True).start() # 主线程专门负责输入 while True: user_input = input() print(f"已存入队列: {user_input}, 队列当前大小: {queue.qsize()}") queue.put(user_input, block=True)
2. 给stdin加锁
如果必须在子线程里处理输入,用线程锁保证同一时间只有一个线程读取stdin:
import queue import threading import sys queue = queue.Queue(maxsize=5) input_lock = threading.Lock() def t(): while True: # 加锁确保只有当前线程能读取输入 with input_lock: # 用sys.stdin.readline替代input,避免换行符问题 user_input = sys.stdin.readline().strip() print('aaa', user_input, queue.qsize()) queue.put(user_input, block=True) threading.Thread(target=t).start()
3. 让主线程彻底阻塞
让主线程一直等待子线程结束,不再参与stdin的争抢:
import queue import threading queue = queue.Queue(maxsize=5) def t(): while True: i = input() print('aaa',i, queue.qsize()) queue.put(i, block=True) t_thread = threading.Thread(target=t) t_thread.start() # 主线程一直等子线程,不会抢输入 t_thread.join()
总结
永远不要让多个线程同时访问stdin,要么用单线程处理输入,要么加锁同步访问。上面三种方法里,第一种是最稳妥的架构设计,能避免很多线程同步问题。
内容的提问来源于stack exchange,提问作者kbsj
相关产品推荐
相关产品推荐

