开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜