Python Timer倒计时退出时while循环额外执行一次问题
Python线程计时器超时后多执行一次循环问题修复

问题根源
你遇到的问题来自两个原因:
- 代码缩进错误:你贴出的代码里,初始化、启动
Timer的逻辑被错误缩进在lose()函数内部、quit()语句之后,这部分代码永远不会执行,计时器根本不会正常启动,需要把这部分代码移出lose()函数,放到主游戏流程中。 - 线程执行逻辑问题:
Timer运行在独立的子线程中,子线程调用quit()无法立刻打断主线程正在阻塞等待的input()调用,必须等用户按下回车完成当前输入,主线程才会继续执行、响应退出请求,就会出现超时后多跑一次循环的现象。
修复方案
用线程安全的事件标志做跨线程通信,不要在子线程直接调用退出方法,同时主动解除input()的阻塞状态,保证超时后程序立刻终止。
修复后的核心代码如下:
import time from threading import Timer, Event from pyfiglet import Figlet f = Figlet() # 线程安全的退出标志 exit_trigger = Event() def lose(): print("\n\nBtzzzzz!!! Times up!") print(f.renderText('Game Over')) exit_trigger.set() # Windows环境下模拟按下回车,解除input阻塞 try: import ctypes ctypes.windll.user32.keybd_event(0x0D, 0, 0, 0) ctypes.windll.user32.keybd_event(0x0D, 0, 2, 0) except: pass # 计时器逻辑移到lose函数外,和主流程同缩进 t = Timer(3.0, lose) t.start() print("\nGuess a word that contains all of the given letters.") print("The letters are: ", end="") count = 1 for question in Question_list: print(question, end="") if count < level: print(" - ", end="") count += 1 print() print(correct_ans) while True: # 进入输入前先检查是否超时 if exit_trigger.is_set(): exit() try: answer = input("Your answer: ") except ValueError: exit() # 拿到输入后二次检查超时标志,避免执行后续答题逻辑 if exit_trigger.is_set(): exit() if len(answer) > level + 2 and level != 5: print(f"The range of letters for the word in this level is between {str(level)} and {str(level + 2)}.") if answer == correct_ans: answer_list.clear() t.cancel() if level != 5: print("Good job! Here comes the next one.") time.sleep(1) break else: print("Wrong answer.Please try again.")
修复说明
- 用
Event做跨线程的状态同步,子线程触发超时时只设置标志位,不直接调用退出方法,避免线程冲突 - 在输入前后两次检查退出标志,一旦触发超时立刻终止程序,不会执行后续的答案判断逻辑
- 增加模拟回车的逻辑,让主线程阻塞的
input()立刻返回,不需要用户手动按回车就能响应超时退出 - 修正了原代码的缩进错误,保证计时器可以正常启动
内容的提问来源于stack exchange,提问作者myonaise_8893
相关产品推荐
相关产品推荐

