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 VARIABLE
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
engineas an argument tosaythread:But I’d be willing to bet that the real problem is that the methods on your
engineobject 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:
…but that will only help if you were doing something else with your
engineobject 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 yourenginein 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.