Python计时器开发:终端局部清屏,同时显示时间与接收输入
Python计时器问题修复方案
原代码核心问题
- 用
os.system('clear')全清屏幕,导致时间显示和输入界面无法共存 - asyncio使用逻辑错误:无限递归调用
printtime且阻塞后续输入流程 - 输入未做类型转换与空值处理,直接传入
datetime.datetime会触发报错 - 无效的
datetime.datetime(0,0,0,0,0,0)判断,Python不允许年份为0 - 计时器剩余时间计算逻辑完全错误
关键修复点
- 部分清屏实现:使用ANSI转义序列定位光标、清除指定行,只刷新时间区域,保留输入界面
- 多线程并行处理:用
threading让时间显示在后台线程运行,不阻塞前台用户输入 - 输入合法性处理:对空输入填充默认值,字符串转整数并做范围校验
- 正确的计时器逻辑:计算目标时间与当前时间的差值,实时显示剩余时长
修正后的完整代码
import time import datetime import threading # 控制时间显示线程的开关 time_running = True def print_time(): while time_running: # 获取当前日期和时间 today = datetime.date.today() current_time = datetime.datetime.now().strftime("%H : %M : %S") # 用ANSI转义序列将光标上移2行,清除行内容后重新打印时间 print("\033[2A\033[K", end="") print(f"The date now is {today}") print(f"The time now is {current_time}\033[K") time.sleep(1) def make_timer(): print("\nSet a predefined timer:") # 处理输入,空值设为当前对应时间字段,字符串转整数 try: y = int(input("Set year (leave blank for current): ") or datetime.datetime.now().year) m = int(input("Set month (leave blank for current): ") or datetime.datetime.now().month) d = int(input("Set day (leave blank for current): ") or datetime.datetime.now().day) h = int(input("Set hour (leave blank for current): ") or datetime.datetime.now().hour) mt = int(input("Set minute (leave blank for current): ") or datetime.datetime.now().minute) s = int(input("Set second (leave blank for current): ") or datetime.datetime.now().second) except ValueError: print("Error: Please enter valid numbers") return make_timer() try: target_time = datetime.datetime(y, m, d, h, mt, s) except ValueError: print("Error: Invalid date/time") return make_timer() # 检查目标时间是否在未来 if target_time <= datetime.datetime.now(): print("Error: Timer must be set to a future time") return make_timer() print(f"Timer set to: {target_time}") print("Time remaining:") # 实时显示剩余时间 while target_time > datetime.datetime.now(): remaining = target_time - datetime.datetime.now() # 清除当前剩余时间行并打印新值 print("\033[1A\033[K", end="") print(f"{remaining.days} days, {remaining.seconds//3600}h, {(remaining.seconds%3600)//60}m, {remaining.seconds%60}s") time.sleep(1) print("\nTime's up!") # 启动时间显示后台线程 time_thread = threading.Thread(target=print_time) time_thread.daemon = True # 主线程结束时自动退出后台线程 time_thread.start() # 运行计时器设置逻辑 make_timer() # 停止时间显示线程 time_running = False
代码说明
- ANSI转义序列:
\033[2A让光标上移2行,\033[K清除光标所在行内容,仅刷新时间区域不干扰输入界面 - 后台线程:用
threading.Thread创建后台线程处理时间刷新,主线程专注输入和计时器逻辑,实现并行操作 - 输入处理:用
or运算符处理空输入,默认使用当前时间对应字段,同时捕获类型错误和无效日期异常 - 剩余时间计算:通过
datetime对象减法得到时间差,实时格式化显示剩余的天、时、分、秒
内容的提问来源于stack exchange,提问作者reallybadprogrammer
相关产品推荐
相关产品推荐

