Python 用线程同时做两件事
Python two things at the same time with threading
我正在创建一个小程序,只是为了好玩,它可以打开程序并执行类似的操作。
我正在进行维基百科搜索,程序会读出它,我希望 MessageBoxW 将文本写到屏幕上。
我希望这两件事同时发生,因为现在它首先显示消息框,在我关闭 window 之后它正在读取文本
def Mbox(title, text, style):
return ctypes.windll.user32.MessageBoxW(0, text, title, style)
def Mbox(title, text, style):
return ctypes.windll.user32.MessageBoxW(0, text, title, style)
def wikipediaSearch():
global user_input
user_input = user_input.replace("search", '')
result = wikipedia.summary(user_input, sentences=2)
raw_text = result
convert_text = unicodedata.normalize('NFKD', raw_text).encode('ascii', 'ignore')
convert_text = convert_text.decode('utf-8')
new_text = re.sub(r'\(.*\)', '', convert_text)
print(new_text)
Mbox(user_input, new_text, 0)
voice.say(new_text)
voice.runAndWait()
创建一个在单独的线程中运行 pyttsx
的助手 class:
import threading
import pyttsx
class Say(object):
"""Function-like class to speak using pyttsx."""
_thread = None
def __init__(self, message):
if not isinstance(message, str):
raise ValueError("message is not a string")
if Say._thread is not None:
Say._thread.join()
Say._thread = None
Say._thread = threading.Thread(target=self._worker,
name="Say",
args=(message,))
Say._thread.start()
def _worker(self, message):
engine = pyttsx.init()
engine.say(message)
engine.runAndWait()
def WaitAllSaid():
if Say._thread is not None:
Say._thread.join()
Say._thread = None
因为pyttsx的行为像一个singleton,并且任何时候在同一个Python进程中只有一个pyttsx实例可以说话,所以我将全局变量封装到Say
class,并让实例构造函数等待任何现有话语完成,然后启动一个新线程让 pyttsx 说话。
本质上,Say(message)
等待任何正在进行的话语完成,然后开始说出新的声音,然后 returns。它不会等到消息完全说完才开始returns;它 returns 消息开始时立即。
WaitAllSaid()
等待正在进行的任何话语,然后获取工作线程。如果要修改 pyttsx 引擎或语音属性,请先调用 WaitAllSaid()
以确保当时没有正在进行的话语。否则可怜的 pyttsx 可能会感到困惑。
OP 的 wikipediaSearch
函数的最后四行现在变成了
print(new_text)
Say(new_text)
Mbox(user_input, new_text, 0)
WaitAllSaid()
如果 pyttsx 已经在说话,那么 Say()
会阻塞,直到前面的所有消息都被说完。它 returns 当指定的消息开始播放时立即。
WaitAllSaid()
只是 blocks 直到所说的一切都说完。您可以从 wikipediaSearch()
函数中省略它,只要您确保在 Python 程序退出之前调用 WaitAllSaid()
。
关于不完全常规的设计:至少在 Linux 上,如果试图对不同的语句使用相同的 pyttsx 对象,pyttsx 就会出现问题。让辅助线程创建实例效果更好。在 Linux 上测试,该模式是全局变量和各种形式的单例 classes 中最健壮的模式。我根本不使用 Windows,所以我无法对其进行测试,唉。
我正在创建一个小程序,只是为了好玩,它可以打开程序并执行类似的操作。
我正在进行维基百科搜索,程序会读出它,我希望 MessageBoxW 将文本写到屏幕上。
我希望这两件事同时发生,因为现在它首先显示消息框,在我关闭 window 之后它正在读取文本
def Mbox(title, text, style):
return ctypes.windll.user32.MessageBoxW(0, text, title, style)
def Mbox(title, text, style):
return ctypes.windll.user32.MessageBoxW(0, text, title, style)
def wikipediaSearch():
global user_input
user_input = user_input.replace("search", '')
result = wikipedia.summary(user_input, sentences=2)
raw_text = result
convert_text = unicodedata.normalize('NFKD', raw_text).encode('ascii', 'ignore')
convert_text = convert_text.decode('utf-8')
new_text = re.sub(r'\(.*\)', '', convert_text)
print(new_text)
Mbox(user_input, new_text, 0)
voice.say(new_text)
voice.runAndWait()
创建一个在单独的线程中运行 pyttsx
的助手 class:
import threading
import pyttsx
class Say(object):
"""Function-like class to speak using pyttsx."""
_thread = None
def __init__(self, message):
if not isinstance(message, str):
raise ValueError("message is not a string")
if Say._thread is not None:
Say._thread.join()
Say._thread = None
Say._thread = threading.Thread(target=self._worker,
name="Say",
args=(message,))
Say._thread.start()
def _worker(self, message):
engine = pyttsx.init()
engine.say(message)
engine.runAndWait()
def WaitAllSaid():
if Say._thread is not None:
Say._thread.join()
Say._thread = None
因为pyttsx的行为像一个singleton,并且任何时候在同一个Python进程中只有一个pyttsx实例可以说话,所以我将全局变量封装到Say
class,并让实例构造函数等待任何现有话语完成,然后启动一个新线程让 pyttsx 说话。
本质上,Say(message)
等待任何正在进行的话语完成,然后开始说出新的声音,然后 returns。它不会等到消息完全说完才开始returns;它 returns 消息开始时立即。
WaitAllSaid()
等待正在进行的任何话语,然后获取工作线程。如果要修改 pyttsx 引擎或语音属性,请先调用 WaitAllSaid()
以确保当时没有正在进行的话语。否则可怜的 pyttsx 可能会感到困惑。
OP 的 wikipediaSearch
函数的最后四行现在变成了
print(new_text)
Say(new_text)
Mbox(user_input, new_text, 0)
WaitAllSaid()
如果 pyttsx 已经在说话,那么 Say()
会阻塞,直到前面的所有消息都被说完。它 returns 当指定的消息开始播放时立即。
WaitAllSaid()
只是 blocks 直到所说的一切都说完。您可以从 wikipediaSearch()
函数中省略它,只要您确保在 Python 程序退出之前调用 WaitAllSaid()
。
关于不完全常规的设计:至少在 Linux 上,如果试图对不同的语句使用相同的 pyttsx 对象,pyttsx 就会出现问题。让辅助线程创建实例效果更好。在 Linux 上测试,该模式是全局变量和各种形式的单例 classes 中最健壮的模式。我根本不使用 Windows,所以我无法对其进行测试,唉。