如何实现循环播放声音并按ENTER停止,添加后台计数器?
解决方案
问题1:声音循环播放并按ENTER停止
pygame.mixer 的 play(-1) 参数已经支持音频无限循环。要实现按ENTER键停止播放且不阻塞其他操作,我们可以用线程监听用户输入,避免主线程被卡死:
- 创建独立线程等待用户输入,一旦检测到ENTER,立即调用
ringtone.stop()终止音频。 - 该线程不会影响主线程或后台计数器的运行。
问题2:后台运行的计数器
使用Python的 threading 模块创建后台线程,让计数器在后台独立执行,同时主线程可以正常处理输入、打印等操作:
- 将线程设置为
daemon=True,确保主线程退出时后台线程自动终止。 - 用
threading.Event作为信号量,控制计数器的启停,避免线程无法正常结束。
修改后的完整代码
import time import sys import threading from time import strftime, localtime from pygame import mixer import os import pyautogui as spam mixer.init() # 初始化pygame mixer tick = mixer.Sound('sounds/245764888.mp3') def delete_last_line(): sys.stdout.write('\x1b[1A') sys.stdout.write('\x1b[2K') def clock(): current_time = strftime("At: %a, %d %b %Y %H:%M:%S %p", localtime()) print(current_time) def tk(): for i in range(2): print(".") time.sleep(0.3) delete_last_line() print("..") time.sleep(0.3) delete_last_line() print("...") time.sleep(0.3) delete_last_line() print("....") time.sleep(0.3) delete_last_line() ringtone = mixer.Sound('sounds/pill.wav') # 加载提示音文件 # 后台计数器逻辑 def background_counter(stop_event): count = 0 while not stop_event.is_set(): # 用\r覆盖当前行,避免控制台刷屏 print(f"后台计数器: {count}", end='\r') count += 1 time.sleep(1) while True: samay = 0 os.system("cls") print("Started", end=" "); clock() time_inout_frm_usr = int(input('\nEnter the times in seconds: ')) while samay < time_inout_frm_usr: samay += 1 tick.play() print(samay) time.sleep(1) delete_last_line() if samay == time_inout_frm_usr: ringtone.play(-1) # 无限循环播放提示音 print('\nTIME OUT!!!\n') print("Ended", end=" "); clock() # 创建停止事件,用于同步线程停止信号 stop_event = threading.Event() # 启动后台计数器线程(守护线程) counter_thread = threading.Thread(target=background_counter, args=(stop_event,), daemon=True) counter_thread.start() # 监听用户输入的线程 def wait_for_stop(): input("Press Enter to stop") ringtone.stop() stop_event.set() # 通知后台计数器停止 stop_thread = threading.Thread(target=wait_for_stop) stop_thread.start() stop_thread.join() # 等待用户输入完成 delete_last_line() break ask_cont = input("\nTo use again [ENTER] to continue or [NO] to close: ") if ask_cont == '': delete_last_line() print("Starting again in a sec") tk() else: os.system("cls") print("Closing in a sec") tk() spam.typewrite("exit") spam.press("Enter") break
关键修改说明
- 多线程处理:
- 新增
background_counter函数,通过stop_event控制计数器启停,在后台独立运行。 - 超时后启动两个线程:一个监听用户输入,一个运行后台计数器,避免主线程阻塞。
- 新增
- 音频控制:
- 保留
ringtone.play(-1)实现无限循环,通过输入监听线程触发ringtone.stop()终止播放。
- 保留
- 控制台优化:
- 后台计数器用
end='\r'覆盖当前行,避免控制台被重复打印刷屏。
- 后台计数器用
内容的提问来源于stack exchange,提问作者Eco
相关产品推荐
相关产品推荐

