0

I am trying to call a take_command() function from main.py.

The system prints the value right before the return call, but doesn't actually return the value to main.py. The take_command() function was working fine before I refactored and added in the start_recognizer() and callback() functions to run constantly and listen for triggers.

I know I must be missing something very simple in my refactor but honestly have not been able to find the issue.

command.py:

import time
import speech_recognition as speech

listener = speech.Recognizer()
keywords = [("randy", 1), ("hey randy", 1), ]
source = speech.Microphone()


def start_recognizer():
    print("Listening...")
    listener.listen_in_background(source, callback)
    time.sleep(1000000)


def callback(recognizer, audio):  # This is called from the background thread
    try:
        speech_as_text = recognizer.recognize_sphinx(audio, keyword_entries=keywords)
        print(speech_as_text)

        # Look for your "Ok Google" keyword in speech_as_text
        if "randy" in speech_as_text or "hey randy":
            take_command()

    except:
        pass


def take_command():
    print("Recognizing Main...")
    voice = listener.listen(source)
    the_command = listener.recognize_google(voice)
    the_command.lower()
    print(the_command)
    return the_command

    # Interpret the user's words however you normally interpret them

main.py:

from lib import jokes
from lib import engine
from lib import time
from lib import command
from lib import wikipedia
from lib import youtube


def run_randy():
    user_command = command.start_recognizer()
    print('in main' + user_command)
    if 'play' in user_command:
        engine.talk('playing' + youtube.play_song(user_command))
    elif 'joke' in user_command:
        engine.talk(jokes.jokes())
    elif 'time' in user_command:
        engine.talk('Current time is ' + time.get_time())
    elif 'who is' in user_command:
        engine.talk(wikipedia.get_person(user_command))
    else:
        engine.talk('Please say the command again.')


while True:
    run_randy()

The output is this:

Listening...
hey randy  randy 
Recognizing Main...
in take_command(): tell me a joke
Ted Klein Bergman
  • 9,146
  • 4
  • 29
  • 50
abristow
  • 3
  • 3
  • What do you mean by "doesn't actually return the value to main.py"? What is does the function return? Please show example output when you run your code. – Code-Apprentice Jan 27 '22 at 21:17
  • 2
    Obligatory warning: Never use bare `except`. **Always** catch the specific error you expect. Otherwise you'll likely fall into situations where your program works but doesn't do what you expect. – Ted Klein Bergman Jan 27 '22 at 21:17
  • 2
    Also, `"randy" in speech_as_text or "hey randy"` will **always** be `True`. See [this](https://stackoverflow.com/questions/15112125/how-to-test-multiple-variables-for-equality-against-a-single-value). – Ted Klein Bergman Jan 27 '22 at 21:18
  • 2
    Also, please remove all unnecessary code, i.e. things that aren't necessary for the problem to occur, to shorten it as much as possible (of course without removing the problem). One example is all the code that's been commented out, or the imports you don't use, as currently it's just noise that distracts from the issue. See [mcve]. – Ted Klein Bergman Jan 27 '22 at 21:19
  • @Code-Apprentice it just stops at the print statement right before return. So in main.py, this line is never ran: ```print('in main' + user_command)``` This is the console: ```Listening... hey randy randy Recognizing Main... tell me a joke``` – abristow Jan 27 '22 at 21:19
  • @TedKleinBergman edited – abristow Jan 27 '22 at 21:22
  • Why do you think that output "proves" that the `return` isn't reached? What do you think the output _should_ be? – Charles Duffy Jan 27 '22 at 21:27
  • The triple-ticks (`\`\`\``) needs to be on their own line, otherwise the text on the same line won't be rendered. – Ted Klein Bergman Jan 27 '22 at 21:27
  • The code that calls `take_command` doesn't do anything with its return value, so I don't know how you think you know anything about what that return value is. It's thrown away, no matter what it is, so you can't tell what it was from the larger program's output. – Charles Duffy Jan 27 '22 at 21:29
  • @CharlesDuffy when in debugging mode the ```print('in main' + user_command)``` is never even reached. The debugger gets ```print(the_command)``` in take_command() and stops. the same value printed in take_command() should also be printed in the main method immediately after. – abristow Jan 27 '22 at 21:30
  • @CharlesDuffy the same take_command() function was performing as expected before I refactored and added in the above mentioned functions. – abristow Jan 27 '22 at 21:31
  • you have an extra `,` in `keywords` – pugi Jan 27 '22 at 21:36
  • @CharlesDuffy ok that is starting to make sense to me. How would I go about being able to return the command back to main.py? – abristow Jan 27 '22 at 22:09
  • has anyone been able to find the solution? I've still yet to fix this problem. – abristow Jan 27 '22 at 22:58
  • I haven't seen you prove that there _is_ any problem in the first place (at least, a problem with `return` not being reached -- your code has lots of other problems, as described by other commenters above). If you can't prove to us that there exists a problem, how is anyone supposed to know if they've fixed it? – Charles Duffy Jan 27 '22 at 23:04
  • 1
    Using `except: pass` is a problem (one that hides other problems and makes your code impossible to debug, because errors just get silently swallowed instead of being shown). Using `if "randy" in speech_as_text or "hey randy"` is a problem (because it makes your `if` condition basically equivalent to `if True:`). But you're not only not fixing those problems, you seem to be ignoring the people who tell you they exist. So how are we supposed to help you? – Charles Duffy Jan 27 '22 at 23:06
  • 1
    Part of why we ask for a [mre] is to have code that's minimal enough that it has _only one problem_, so you don't have other problems that get in the way of being able to address the specific one the question is about. – Charles Duffy Jan 27 '22 at 23:09
  • @abristow "it just stops at the print statement right before return" That's not possible. This isn't how computers work. Execution *MUST* continue. – Code-Apprentice Jan 28 '22 at 17:32
  • Your output doesn't match your code. I don't see anywhere that prints "In take_command()". – Code-Apprentice Jan 28 '22 at 17:37

2 Answers2

0

It is a bit hard to read, but I think you need to return in the callback() function? i.e. :

def callback(...):
    ...
    return take_command()
Anynamer
  • 334
  • 1
  • 6
0

There are multiple problems with your code as mentioned in the comments. However, the issue that you are asking about is a problem with your expectations about how the code works. I expect that user_command = command.start_recognizer() is blocking. start_recognizer() certainly never returns an explicit value, so if it ever does return, it will return None, not a command as you seem to expect.

I suggest you find the documentation for the Recognizer class and its listen_in_background() method in order to better understand what your code is doing. My guess is that listen_in_background() has an infinite loop to continue listening to the microphone. This means it will never return back to run_randy() to print out the output there.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268