You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python打字速度测试:线程实现及循环超时未停止问题修复

打字速度测试工具:循环停止修复与线程使用指南

一、先解决你的循环不停止问题

你的代码里有两个关键问题导致时间到了还停不下来:

  1. 外层while循环用的是初始化时的currenttime,这个值自始至终没更新过——不过你内部用now_time做了判断,这个问题不算致命;
  2. 嵌套的for循环会把所有单词挨个跑完,而且input()是阻塞调用——哪怕时间早就到了,程序也得等你把当前单词输完,把整个列表遍历完才会退出。

下面是修复后的代码,顺便把你要的随机单词功能加上:

import datetime
import random

word_list = ['hello', 'darkness', 'my', 'old', 'friend', 'fox']
print("You have 1 minute to type all the words you can")
start = input('Press y to start or n to exit: ').lower()

wrong = []
correct = []
total = []

if start == 'y':
    test_duration = 60
    end_time = datetime.datetime.now() + datetime.timedelta(seconds=test_duration)
    print(f"Test started! You have {test_duration} seconds.")

    while datetime.datetime.now() < end_time:
        # 每次循环先检查剩余时间
        remaining = (end_time - datetime.datetime.now()).total_seconds()
        if remaining <= 0:
            print('\nTime is up!')
            break
        
        # 随机选一个单词
        current_word = random.choice(word_list)
        print(f"\nType this: {current_word}")
        
        # 这里还是会等你输入完,但至少每次输入前会确认时间
        user_input = input().strip()
        total.append(current_word)
        
        if user_input == current_word:
            correct.append(current_word)
        else:
            wrong.append(current_word)

# 计算WPM(标准算法:每分钟输入单词数,按每个单词5字符的统计方式)
wpm = len(total) / (test_duration / 60) if test_duration else 0
accuracy = (len(correct)/len(total))*100 if total else 0

print(f'\n--- Results ---')
print(f'Total words typed: {len(total)}')
print(f'Correct: {len(correct)} | Wrong: {len(wrong)}')
print(f'WPM: {round(wpm, 2)}')
print(f'Accuracy: {round(accuracy, 2)}%')

二、要不要用threading?

不用线程的局限

上面的修复代码能正常工作,但有个小瑕疵:如果在最后几秒你开始输入一个单词,哪怕时间到了,程序也得等你输完才会结束。这是因为input()会卡住主线程,没法中途打断。

用线程的好处

如果想实现时间一到立刻终止输入提示的效果,就得用线程。我们可以开一个线程专门计时,主线程处理输入,计时线程到点后设置一个标志,主线程根据这个标志决定是否继续。

给你一个线程版的示例:

import datetime
import random
import threading
import time

word_list = ['hello', 'darkness', 'my', 'old', 'friend', 'fox']
print("You have 1 minute to type all the words you can")
start = input('Press y to start or n to exit: ').lower()

wrong = []
correct = []
total = []
time_expired = False  # 标记时间是否到了

def countdown_timer(duration):
    global time_expired
    time.sleep(duration)
    time_expired = True
    print('\nTime is up!')

if start == 'y':
    test_duration = 60
    # 启动计时线程,daemon=True保证主线程结束时它也跟着结束
    threading.Thread(target=countdown_timer, args=(test_duration,), daemon=True).start()
    print(f"Test started! You have {test_duration} seconds.")

    while not time_expired:
        current_word = random.choice(word_list)
        print(f"\nType this: {current_word}")
        
        # 用线程处理输入,避免主线程一直被input()卡住
        user_input = None
        def get_user_input():
            nonlocal user_input
            user_input = input().strip()
        
        input_thread = threading.Thread(target=get_user_input)
        input_thread.start()
        
        # 每秒检查一次时间是否到了,不用一直等输入
        input_thread.join(timeout=1)
        if time_expired:
            break
        
        if user_input is not None:
            total.append(current_word)
            if user_input == current_word:
                correct.append(current_word)
            else:
                wrong.append(current_word)

# 计算结果
wpm = len(total) / (test_duration / 60) if test_duration else 0
accuracy = (len(correct)/len(total))*100 if total else 0

print(f'\n--- Results ---')
print(f'Total words typed: {len(total)}')
print(f'Correct: {len(correct)} | Wrong: {len(wrong)}')
print(f'WPM: {round(wpm, 2)}')
print(f'Accuracy: {round(accuracy, 2)}%')

这个版本里,计时线程到点后会把time_expired设为True,主线程每秒检查一次这个标志,一旦时间到了就立刻停止等待输入。

总结

  • 如果你能接受“时间到后等用户输完当前单词再结束”,完全不用线程,修复循环逻辑就够了;
  • 如果你想要更丝滑的体验,时间到了立刻终止输入,可以用线程来实现。

内容的提问来源于stack exchange,提问作者TwinkleTwinkle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 09:16:14