Search code examples
pythonconcurrent.futures

Why does the code with the concurrent.futures.thread skip widget operations?


The goal is to first perform actions on widgets (create Button_1 and remove Button_2) and then enable speech recognition.

I should definitely use the concurrent.futures.thread module.

In this attempt, the compiler goes through each line-this is evidenced by the output of lines marked with #for test comments. Problem: speech recognition works, but actions with buttons (create Button_1 and remove Button_2) occur only after exit from functions voiceRecognition:

def someFunc(self, event):
    print('Interface change started') #for test
    #creates Button_1
    #deletes config.Button_2 (from another func)
    print('Interface change finished') #for test

    with ThreadPoolExecutor(max_workers=5) as executor:
        fut = executor.submit(self.voiceRecognition)

def voiceRecognition (self):
    print('Voice recognition was started') #for test
    r = sr.Recognizer()
    with sr.Microphone(device_index=1) as sourse:
        audio = r.listen(sourse)
        query = r.recognize_google(audio)
        print(query.lower())
        print('Voice recognition was finished') #for test

Output :

Interface change started
Interface change finished
Voice recognition started
Voice recognition finished

Here is, as and that with buttons specifically (separately from context they work, and work normally) :

config.Button_1 = wx.Button(self)
self.Bind(wx.EVT_BUTTON, self.eventFunc, Button_1)
config.Button_2.Destroy()

Help me to understand the causes of problems and their practical solution. Thanks.


Solution

  • The problem you are having is

    1.you are only calling one thread for the voice recognition function which only runs one time

    1. my second guess would be that these functions are not i/o bound functions

    The way threads work is another function starts while the previous is waiting for a particular data to be received or something similar. If there are no such requirements then threads are not very usefulenter image description here

    The point which the second function starts running is the point at which the first function is waiting to receive some resource. If this is not your requirements you may want to look into multiprocessing or async/await functions(using the asyncio package)

    import asyncio
    
    async def someFunc(event):
        print('Interface change started') #for test
        #creates Button_1
        
        await event() #when code runs with voiceRecognition past as the event parameter, that is what will run here
    
        #deletes config.Button_2 (from another func)
        print('Interface change finished') #for test
    
    def voiceRecognition ():
        print('Voice recognition was started') #for test
        r = sr.Recognizer()
        with sr.Microphone(device_index=1) as sourse:
            audio = r.listen(sourse)
            query = r.recognize_google(audio)
            print(query.lower())
            print('Voice recognition was finished') #for test
    
     asyncio.run(someFunc(voiceRecognition)) #to run it asynchronously
    

    I do not really know how your class looks so i have written it as a typical function, meaning you will have to adapt it a little to fit your code.

    Notice the change to how your voiceRecognition() is called in someFunc using your event parameter and also notice the position event is now called at in someFunc