Scoping rules and threads
This is the program that works (I am able to hear the text to speech in action):
import pyttsx
import threading
def saythread(location, text):
engine = pyttsx.init()
engine.say(text)
engine.runAndWait()
e = (1, "please work, oh my god")
t = threading.Thread(target=saythread,args=e,name='sayitthread')
t.start()
If the program is changed to
import pyttsx
import threading
def saythread(location, text):
global engine #(CHANGED) ADDED GLOBAL
engine.say(text)
engine.runAndWait()
e = (1, "please work, oh my god")
engine = pyttsx.init() #(CHANGED) ADDED VA开发者_JAVA技巧RIABLE
t = threading.Thread(target=saythread,args=e,name='sayitthread')
t.start()
Then it gets 'stuck' at the line "engine.runAndWait()" and text to speech doesn't work. I am guessing that the problem lies with the rules of scoping with threads. right? Basically what I want is a.. a 'handle' to the engine variable in my main thread. So that i can call engine.stop() from the main thread.
Hope I made sense
Thanks
Global variables are almost always a bad approach. You can just pass engine
as an argument to saythread
:
def saythread(engine, location, text):
engine.say(text)
engine.runAndWait()
# ...later...
engine = pyttsx.init() #(CHANGED) ADDED VARIABLE
t = threading.Thread(target=saythread,args=(engine, 1, "here we go"),name='sayitthread')
t.start()
But I'd be willing to bet that the real problem is that the methods on your engine
object aren't designed to be called from other threads. (Scoping has nothing to do with it, by the way, it depends on the design of the underlying library.)
It might be that you can get around the problem using a lock:
def saythread(engine, lock, location, text):
with lock:
engine.say(text)
engine.runAndWait()
engine = pyttsx.init()
lock = threading.Lock()
t = threading.Thread(
target=saythread,
args=(engine, lock, 1, "here we go"),
name='sayitthread')
t.start()
...but that will only help if you were doing something else with your engine
object concurrently that it didn't like. From your code, that doesn't look like it's the case, so you might have to live with creating each engine object within the thread, and finding another way to pass around state. Alternatively, you can keep your engine
in the main thread, and use a queue to call it from other threads where you're doing other work.
It's worth remembering that not all Python libraries (especially those that are written in C) support threads at all, so you have to be careful, read the documentation or ask the author.
精彩评论