基于Python Tkinter开发语音助手遇两类技术问题求助
Let's break down your two issues and fix them step by step:
Issue 1: Infinite Loop Repeating the Same Reply
Your assistant keeps spamming "I am doing jolly good, sir." because of two key problems in the reply() function:
- Broken condition logic: The line
elif 'how are you' or 'what\'s up' in query:is alwaysTrue(since non-empty strings evaluate toTruein Python). This means no matter what your query actually says, this branch will trigger if none of the earlier conditions match. - Unbounded
while Trueloop: There's no mechanism to fetch a new query or exit the loop, so once this broken condition triggers, it runs forever.
Fix for Issue 1:
def reply(): global query while True: # Exit condition to break the loop (add your own trigger phrase) if 'exit' in query or 'quit' in query: speak("Goodbye sir!") break # Logic for executing tasks based on query if 'wikipedia' in query: speak('Searching Wikipedia...') query = query.replace("wikipedia", "").replace("search", "").replace("for", "") results = wikipedia.summary(query.strip(), sentences=1) speak(f'According to Wikipedia, {results}') elif 'open youtube' in query: speak('Opening Youtube') webbrowser.open("https://youtube.com") elif 'open stack overflow' in query: speak('Opening StackOverflow') webbrowser.open("https://stackoverflow.com") elif 'what' in query and 'time' in query: strTime = datetime.datetime.now().strftime("%H:%M:%S") speak(f"Sir, The time is {strTime}") # Fixed condition check: both phrases need to be checked against query elif 'how are you' in query or 'what\'s up' in query: speak('I am doing jolly good, sir.') else: speak("Sorry, I didn't understand that.") # Fetch a new query after processing the current one query = listen_to_me()
Key changes made:
- Fixed the broken
elifcondition to properly check if either phrase exists inquery - Added an exit condition to break the loop when you say "exit" or "quit"
- Added an
elsebranch for unrecognized commands - Added
query = listen_to_me()at the end of the loop to fetch a new voice input after each response
Issue 2: AttributeError When Converting Query to Lowercase
The error AttributeError: 'list' object has no attribute 'lower' happens because you're using show_all=True in r.recognize_google(). This parameter makes the function return a list of dictionaries (all possible recognition results) instead of a single string. When you try to call .lower() on a list, Python throws an error.
Fix for Issue 2:
Option 1 (Recommended: Use only the top recognition result):
Remove show_all=True to get a single string result, then you can safely convert it to lowercase:
def listen_to_me(): msg2 = Message(root, text="Listening...", bg='yellow', font=('times', 14, 'italic')) msg2.place(x=200, y=220) # Removed unused msg2.pack (it's redundant with place) with sr.Microphone() as source: audio = r.listen(source) global query try: # Removed show_all=True to get a single string result query = r.recognize_google(audio, language='en-IN') query = query.lower() # Now this works! print(f"[Me]: {query}") except sr.UnknownValueError: engine.say("Sorry didn't quite catch that. Please repeat.") query = "" except sr.RequestError: engine.say("Sorry, I can't connect to the speech recognition service right now.") query = "" return query
Option 2 (If you need all recognition results):
If you must keep show_all=True, extract the transcript from the first result before calling .lower():
def listen_to_me(): msg2 = Message(root, text="Listening...", bg='yellow', font=('times', 14, 'italic')) msg2.place(x=200, y=220) with sr.Microphone() as source: audio = r.listen(source) global query try: # Get all results as a list of dicts all_results = r.recognize_google(audio, language='en-IN', show_all=True) if all_results: # Extract the top result's transcript query = all_results['alternative'][0]['transcript'].lower() print(f"[Me]: {query}") else: engine.say("Sorry didn't quite catch that. Please repeat.") query = "" except sr.UnknownValueError: engine.say("Sorry didn't quite catch that. Please repeat.") query = "" except sr.RequestError: engine.say("Sorry, I can't connect to the speech recognition service right now.") query = "" return query
Key changes made:
- Fixed the
show_all=Trueissue by either removing it (for a single string) or extracting the transcript from the result list - Added proper error handling for speech recognition errors (UnknownValueError and RequestError)
- Fixed the unused
msg2.packcall (it's redundant withplace())
内容的提问来源于stack exchange,提问作者DC007744

