下午,同事问我:有办法终止一个阻塞的raw_input吗?
他希望:用户既可以在终端标准输入,也可以选择外部手机扫码输入。任意条件满足的情况下,程序都能继续向后执行。
但是,上述raw_input会阻塞,导致不能检查是否有成功扫码。
为了得到想要的效果,我写了一个示例程序,方法如下:
从终端读取标准输入的阻塞操作,必然不能在原先的函数中执行,交由子进程处理
扫码确认的动作,交给1个单独线程轮询处理,这里,我换成了本地文件读取演示
# -*- coding: utf-8 -*-
import threading
import sys
import os
import time
import multiprocessing
def get_input(file_no, queue_motp):
stdin_obj = os.fdopen(file_no)
code = stdin_obj.readline().strip()
queue_motp.put(code)
stdin_obj.close()
class GetMOTP(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
global flag
self.motp_input_done = False
sys.stdout.write("motp>")
manager = multiprocessing.Manager()
self.queue_motp = queue_motp = manager.Queue()
p = multiprocessing.Process(target=get_input, args=(sys.stdin.fileno(), queue_motp)) # 读取标准输入
p.start()
threading.Thread(target=self.check_from_disk).start() # 本地读取
while queue_motp.empty():
time.sleep(0.1)
self.motp_input_done = True
p.terminate()
motp = queue_motp.get_nowait()
print("motp: ", motp)
if motp == "good":
flag = True
# 模拟扫码逻辑
def check_from_disk(self):
while not self.motp_input_done:
if os.path.exists("motp.txt"):
with open("motp.txt", "r") as f:
code = f.read()
if code.strip():
self.queue_motp.put(code.strip())
return True
time.sleep(0.2)
if __name__ == '__main__':
GetMOTP().start()
以上,无论是用户在终端输入,还是扫码轮询成功,都可以取到输入,并同时终止2类等待,继续执行后续的程序逻辑。