如何在倒计时运行时同步触发密码输入请求?
问题原因
你写的线程创建逻辑有本质错误:
当你写
Thread(target=generateCodeandTimer(600))时,Python不会等start()调用才运行这个函数,而是在主线程执行到这行代码时,就会立刻同步执行generateCodeandTimer(600),直到这个函数完整跑完(也就是10分钟倒计时全部走完、返回结果之后),才会继续执行后面创建Thread2、启动两个线程的代码。
这时候两个线程启动的时候,倒计时早就结束了,自然会出现你说的「必须等倒计时走完才弹出输入请求」的现象,和多线程并行的预期完全不符。
threading.Thread的target参数需要接收函数对象本身,不能直接加括号调用函数,函数要传的参数需要单独通过args参数(元组类型)传入。
另外你现有逻辑还缺一个核心判断:倒计时结束后就算输入框已经弹出来,也要拦截提交、判定失效。
修正步骤
- 修正线程创建的传参写法,把直接调用函数改成传函数名+通过
args单独传参 - 增加全局过期状态标记,倒计时结束时把标记设为已过期
- 输入提交校验时先判断是否已过期,过期直接返回失效提示,不再校验密码
- 调整输出逻辑,避免倒计时的回车刷新和输入提示抢标准输出导致显示错乱
修正后完整代码
import string import random import time import sys import threading code = "" expired = False def generateCodeandTimer(s): global code, expired code = ''.join((random.choice(string.ascii_lowercase + string.digits) for x in range(6))) print("当前考勤验证码:", code) print("请输入验证码完成签到:", end='', flush=True) while s >= 0: mins = s // 60 secs = s % 60 countdown = ' | 剩余有效时间: {:02d}:{:02d}'.format(mins, secs) sys.stdout.write('\r' + code + countdown) sys.stdout.flush() time.sleep(1) s -= 1 expired = True print() print("验证码已过期,签到通道已关闭") def attend(): global expired studentinput = input() if expired: print("验证码已过期,考勤提交失败") return if studentinput == code: print("签到成功,考勤已记录") else: print("验证码错误,签到失败") # 注意传参写法:target只写函数名,参数放args元组中 Thread1 = threading.Thread(target=generateCodeandTimer, args=(600,)) Thread2 = threading.Thread(target=attend) Thread1.start() Thread2.start() Thread1.join() Thread2.join()
补充说明
- 传给
args的元组如果只有一个元素,后面必须加逗号,比如(600,),否则Python会把它识别成普通括号包裹的数字,不是合法的元组类型 - 倒计时刷新输出后加
flush=True是为了强制立刻把内容推到终端显示,避免部分终端缓存输出导致倒计时不实时更新 - 两个线程启动后加
join()是为了等两个线程都执行完再退出主线程,避免主线程提前结束把子线程强制杀掉
内容的提问来源于stack exchange,提问作者Zhe Hin Yap
相关产品推荐
相关产品推荐

