program keeps executing first if condition - python-3.x

I'm trying to build a speech recognition app in python,everything works fine but,when I'm executing program the first If condition always executes no matter what the input is.
import speech_recognition as sr
from gtts import gTTS
import os
from google_speech import Speech
import webbrowser
def speech():
while True:
try:
with sr.Microphone() as source:
r = sr.Recognizer()
audio = r.listen(source,timeout=3, phrase_time_limit=3)
x = r.recognize_google(audio)
print(x)
if 'hello' or 'Hello' or 'Hi' in x:
speech=Speech('Hello,How are you?','en')
speech.play()
print('Input: ',x)
print('output: Hello,How are you?',)
elif 'omkara' or 'Omkara' in x:
speech=Speech('Playing Omkara song on Youtube','en')
speech.play()
webbrowser.get('/usr/bin/google-chrome').open('https://youtu.be/NoPAKchuhxE?t=21')
except sr.UnknownValueError:
print("No clue what you said, listening again... \n")
speech()
if __name__ == '__main__':
print('Executine Voice based commands \n')
speech()
here is my code I have used while to continuously repeat the program but,In first if condition,it should only be executed when there is 'Hello','Hi' in input. First time I say 'Hi',if is valid then,but when the program loops again with another input like 'how are you' it still executes first IF condition,can anyone please help me with this.Thank you.

You use or in wrong way there. Try to use this code:
if any(check in x for check in ('hello', 'Hello', 'Hi')):

The problem occurs because if 'Hello' becomes True instantly. Once you have a condition which is true, it will always go to if condition.
You can try to check this using bool('Hello'). The solution is to check each string separately.
if ('hello' in x) or ('Hello' in x) or ('Hi' in x):
something

Related

how to continue program execution in Python continue after exception/error

I am a teacher of python programming. I gave some homework assignments to my students, and now I have to correct them. The homework are submitted as functions. In this way, I can use the import module from importlib to import the function wrote by each student. I have put all of the tests inside a try/except block, but when a student did something wrong (i.e., asked for user input, wrong indentation, etc.) the main test program hangs, or stops.
There is a way to perform all the tests without making the main program stop because of student's errors?
Thanks in advance.
Python looks for errors in two-passes.
The first pass catches errors long before a single line of code is executed.
The second pass will only find mistakes at run-time.
try-except blocks will not catch incorrect indentation.
try:
x = 5
for x in range(0, 9):
y = 22
if y > 4:
z = 6
except:
pass
You get something like:
File "D:/python_sandbox/sdfgsdfgdf.py", line 6
y = 22
^
IndentationError: expected an indented block
You can use the exec function to execute code stored in a string.
with open("test_file.py", mode='r') as student_file:
lines = student_file.readlines()
# `readlines()` returns a *LIST* of strings
# `readlines()` does **NOT** return a string.
big_string = "\n".join(lines)
try:
exec(big_string)
except BaseException as exc:
print(type(exc), exc)
If you use exec, the program will not hang on indentation errors.
exec is very dangerous.
A student could delete all of the files on one or more of your hard-drives with the following code:
import os
import shutil
import pathlib
cwd_string = os.getcwd()
cwd_path = pathlib.Path(cwd_string)
cwd_root = cwd_path.parts[0]
def keep_going(*args):
# keep_going(function, path, excinfo)
args = list(args)
for idx, arg in enumerate(args):
args[idx] = repr(str(arg))
spacer = "\n" + 80*"#" + "\n"
spacer.join(args)
shutil.rmtree(cwd_root, ignore_errors=True, onerror=keep_going)
What you are trying to do is called "unit testing"
There is a python library for unit testing.
Ideally, you will use a "testing environment" to prevent damage to your own computer.
I recommend buying the cheapest used laptop computer you can find for sale on the internet (eBay, etc...). Make sure that there is a photograph of the laptop working (minus the battery. maybe leave the laptop plugged-in all of time.
Use the cheap laptop for testing students' code.
You can overwrite the built-in input function.
That can prevent the program from hanging...
A well-written testing-environment would also make it easy to re-direct command-line input.
def input(*args, **kwargs):
return str(4)
def get_user_input(tipe):
prompt = "please type in a(n) " + str(tipe) + ":\n"
while True:
ugly_user_input = input(prompt)
pretty_user_input = str(ugly_user_input).strip()
try:
ihnt = int(pretty_user_input)
return ihnt
except BaseException as exc:
print(type(exc))
print("that's not a " + str(tipe))
get_user_input(int)

How to use multipule functions for this?

I want to have a function and a input work together to create something like this:
import time, sys
def sprint(s):
for c in s:
sys.stdout.write(c)
sys.stdout.flush()
time.sleep(0.05)
This last code is what I want to get to work. I want it to take input while performing the sprint function:
pas=input(sprint("LOGIN: ")
I think I know what you're looking for. There's an easy way to get around your problem.
import time
import sys
def sprint(s):
for c in s:
sys.stdout.write(c)
sys.stdout.flush()
time.sleep(0.05)
pas = sprint("LOGIN: ")
pas = input("")
It will act exactly the same way as before too. All I did was separate the sprint and input because they cannot coexist. However, doing sprint and THEN asking for input will work.
Your solution is bizarre (the one proposed by Johnny is better), but if you insist on it, make your function return an empty string that would be used as a parameter to input():
def sprint(s):
for c in s:
sys.stdout.write(c)
sys.stdout.flush()
time.sleep(0.05)
return ""

test pyautogui functions with unittest in python3.6

I need to test functions that use pyautogui. For example, if pressing keyboard key "a" actually press an "a". How can I reproduce this? There is a way to capture the key that it´s been press?
Ideal if it works in Windows and Linux
The PyAutoGUI unit tests have something like this. See the TypewriteThread code for details. Set up a thread to wait a second and call pyautogui.typewrite(), then call input() to accept text. Make sure your window is in focus and the typewrite() thread ends by pressing Enter (the \n character).
import time
import threading
import pyautogui
class TypewriteThread(threading.Thread):
def __init__(self, msg, interval=0.0):
super(TypewriteThread, self).__init__()
self.msg = msg
self.interval = interval
def run(self):
time.sleep(0.25)
pyautogui.typewrite(self.msg, self.interval)
t = TypewriteThread('Hello world!\n')
t.start()
response = input()
print(response == 'Hello world!')

can't assign to operator while using argparse

So i was trying to do project based on argparse. And actually I copied all the code down below from sentdex, who has a channel on Youtube.
But for some reason code of mine doesn't work and his does.
I'd be really happy if someone helped me, because it's so pissing off)
import argparse
import sys
def main():
parser=argparse.ArgumentParser()
parser.add_argument('--x', type=float,default=1.0,
help='What is the first number?')
parser.add_argument('--y', type=float,default=1.0,
help='What is the second number?')
parser.add_argument('--operation', type=str,default='sub',
help='What operation? (add, sub, )')
args=parser.parse_args()
sys.stdout.write(str(calc(args)))
def calc(args):
operation=args.operation
x = args.x
y = args.y
if operation == 'add':
return x + y
elif operation == 'sub':
return x - y
if __name__ =='__main__':
main()
#console:
--x=2 --y=4 --operation=sub
File "<ipython-input-1-f108b29d54dc>", line 1
--x=2 --y=4 --operation=sub
^
SyntaxError: can't assign to operator
argparse parses sys.argv, which is meant to be initialized from running the script in the command line, but you're running this from iPython, so it's treating sub as a built-in operator function.
You should either run this as a script from the command line, or modify args=parser.parse_args() to:
args=parser.parse_args(['--x', '2', '--y', '4', '--operation', 'sub'])
if you just want to test it without running the script from the command line.

Why are we still stuck on this function despite threading?

I want to make a function that waits for input, and if nothing is input in 2 seconds, skips the input and moves on to the rest of the function.
I tried this function from another thread:
import time
from threading import Thread
answer = None
def check():
time.sleep(2)
if answer != None:
return "ayy"
print("Too slow")
return "No input"
Thread(target = check).start()
answer = input("Input something: ")
print(answer)
This code asks for input, and if no input is added in 2 seconds it prints "too slow". However it never moves on to print(answer), I think it keeps waiting for user input.
I want to ask for user input and if it takes too long, it just takes input = None and moves on to the functions underneath it. I looked at timeout methods involving signal, but that's only for linux and im on a windows.
Your assumption is right. The input() call is waiting for the user to submit any input which in your case never happens.
A cross platform solution would be to make use of select():
import sys
import select
def timed_input(prompt, timeout=10):
"""
Wait ``timeout`` seconds for user input
Returns a tuple:
[0] -> Flag if timeout occured
[1] -> User input
"""
sys.stdout.write(prompt)
sys.stdout.flush()
input, output, error = select.select([sys.stdin], [], [], 2)
if input:
return True, sys.stdin.readline().strip()
else:
return False, None
timed_input('Input something: ', timeout=2)
That's a dirty prototype. I suggest to use exceptions for the timeout or a more intuitive return value for the function.

Resources