问题描述
我正在实现一个简单的Python应用程序,该应用程序在其自己的工作线程中从麦克风运行PocketSphinx识别,并将识别输出通过队列发送到运行Tkinter GUI的主线程。 在辅助线程中,有一个LiveSpeech迭代器类的for循环读取。
现在,当关闭Tkinter窗口时,我也想终止工作线程。问题是它在for循环中(在for phrase in self.__speech:
中的行pocketsphinx_inmic.py
处被阻塞,并且仅在麦克风有任何输入时才继续)。我想找到一种机制,允许我“解除阻止”并让我终止线程(即,在麦克风上没有任何输入)。有人可以建议我怎么做吗?
我正在尝试一些愚蠢的事情,例如尝试使用新的迭代器重写PocketSphinx_InMic .__ speech,希望它可以取消阻止读取,但是没有运气。我找不到LiveSpeech类的实现代码,这使其变得更加困难。 我什至会接受有关如何以某种肮脏的方式杀死线程的建议-这只是一个演示,没有生产代码...
完整代码如下。
pocketsphinx_inmic.py:
from pocketsphinx import Pocketsphinx,get_model_path,LiveSpeech
import nonblock_queue
class PocketSphinx_InMic:
""" Wrapper class for PocketSphinx live recognition from a microphone. Shall be used as backend for the
GUI demo application. """
def __init__(self,queue):
model_path = get_model_path()
self.__config = {
# ...
}
self.__speech = LiveSpeech(**self.__config)
self.__queue = queue
def recog_loop(self):
for phrase in self.__speech:
msg = str(phrase)
self.__queue.enqueue(msg)
nonblock_queue.py:
import queue
class NonblockQueue:
def __init__(self,size = None):
if(size != None):
self.__blck_queue = queue.Queue(maxsize = size)
else:
self.__blck_queue = queue.Queue()
def enqueue(self,msg):
self.__blck_queue.put(msg)
def dequeue(self):
ret = None
try:
ret = self.__blck_queue.get(False)
except queue.Empty:
pass
return ret
...和主要代码:
from pocketsphinx_inmic import PocketSphinx_InMic
import threading
import tkinter as tk
from tkinter import scrolledtext
from nonblock_queue import NonblockQueue
from time import sleep
def set_elem_grid(gui_elem,row_arg,col_arg):
gui_elem.grid(row = row_arg,column = col_arg,padx = GRID_FRAME_PADX,pady = GRID_FRAME_PADY)
if __name__ == "__main__":
print("Starting the main program...")
window = tk.Tk()
window.geometry("640x480")
out_text = scrolledtext.ScrolledText(window,width = SCROLL_TEXT_WIDTH,height = SCROLL_TEXT_HEIGHT)
set_elem_grid(out_text,0)
thr_queue = NonblockQueue()
sphinx = PocketSphinx_InMic(thr_queue)
sphinx_thread = threading.Thread(target = sphinx.recog_loop)
sphinx_thread.start()
while(1):
try:
msg = thr_queue.dequeue()
if(msg):
out_text.insert(index = tk.INSERT,chars = str(msg) + "\n")
window.update_idletasks()
window.update()
sleep(0.1)
except:
# if the window is closed,exception is thrown - just quit Now...
# Todo: we shall kill the second thread gracefully!
exit(0)
解决方法
找到LiveSpeech
类的实现代码后,我发现有一个stop()
方法。但是,它没有达到我的期望。
我最终用threading
替换了multiprocessing
,那里有一个标准的terminate()
方法来终止进程。感觉像是一个过分的杀伤力,但完成了工作。