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

Python线程在while循环首次input时冻结问题求助

问题分析与解决方案

核心错误:队列引用错误

你的代码存在一个致命的低级错误:主循环中你试图往**函数对象read_queue**里添加元素,而非目标队列play_queue。代码里的read_queue.append(song)必须改为play_queue.append(song)。

这个错误直接导致第一次输入的音频路径根本没进入播放队列,播放线程一直在空循环打印"Empty queue"。当你第二次输入时,虽然错误仍存在,但主程序的input阻塞被打破,后续流程因Python函数对象可动态添加属性的特性进入看似正常的状态,但这完全不符合预期逻辑。

线程安全问题

普通列表play_queue的append和pop(0)操作并非线程安全,多线程环境下可能引发数据竞争。建议使用Python标准库的queue.Queue,它原生支持线程安全操作,还自带阻塞等待功能,能大幅简化播放线程的逻辑。

修正后的完整代码

import threading
import time
import soundfile as sf
import sounddevice as sd
from queue import Queue

# 替换为线程安全的Queue
play_queue = Queue()
SPEAKERS_ID = 0  # 请根据你的实际音频设备ID修改

def read_queue():
    while True:
        # Queue.get()会自动阻塞,直到队列有元素,无需手动判断空队列
        print("Getting file...")
        file = play_queue.get()
        print("Calling play function...")
        play(file, SPEAKERS_ID)
        print("Removing from queue...")
        play_queue.task_done()  # 标记任务完成,规范写法

def play(filename, device_id):
    print("Starting play function...")
    try:
        print("Reading file")
        data, fs = sf.read(filename, dtype='float32')
        print("File read")
        print("Playing audio...")
        sd.play(data, fs, device=device_id)
        sd.wait()
        print("Fin del audio.")

    except Exception as e:
        print(f"Un error desconocido ha ocurrido: {e}")

if __name__ == '__main__':
    threading.Thread(target=read_queue, daemon=True).start()

    song = input("Prompt: ")
    while song.lower() != 'exit':
        # 修正队列引用,使用线程安全的put方法
        play_queue.put(song)
        song = input("Prompt: ")

额外优化点

  • 使用queue.Queue的get()方法自动阻塞等待队列元素,省去手动sleep和空队列判断的代码,逻辑更简洁高效。
  • play_queue.task_done()可配合join()方法(若需等待队列所有任务完成再退出程序),当前用daemon线程可省略,但加上更规范。
  • 确保SPEAKERS_ID设置为实际音频输出设备ID,可通过sd.query_devices()命令查看设备列表。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 06:20:37