Why does my code execute like this? I want to break loop when user inputs "Q", but it stops only when I input "Q" 2 times. Sometimes it doesn't even stop after 2 "Q"s. It's purely random.
code
import json
class Kasa:
def __init__(self):
self._running = True
while self._running:
print(self._running)
try:
with open('save.json') as json_file:
DATA = json.load(json_file)
CHOICE = input()
self._running = self.handleEvent(CHOICE)
except IOError:
CHOICE = input()
self._running = self.handleEvent(CHOICE)
def handleEvent(self, event):
if event == 'C':
pass
elif event == 'Q':
return False
else:
return True
if __name__ == "__main__":
Kasa().__init__()
exec output
>>>python file.py
True
True
True
True
True
Q
True
True
True
Q
#script stopped executing here
No need to explicitly call init,
calling Kasa() class will automatically call init
if __name__ == "__main__":
Kasa()
I would rather suggest to write the logic outside init in a seperate method
Related
Directions:
Write a helper function to validate user input. Function should take inputs until valid. Invalid inputs return error message and repeat the prompt. Valid inputs return to main().
User inputs "1" to "5" each print a unique string. User input "0" exits program.
Everything should be executed from within a main() function. Only the call to main() and function definitions are global.
import sys
def getValidInput(selection):
if selection == "1":
return print("message_1")
elif selection == "2":
return print("message_2")
elif selection == "3":
return print("message_3")
elif selection == "0":
print("goodbye")
sys.exit()
else:
return print("That is not a valid option.")
def main():
askAgain = True
while askAgain == True:
getValidInput(selection = input("Select number 1, 2, 3. 0 exits program."))
in __name__ == "__main__":
main()
My question/issue is that while the sys.exit works to terminate the execution, I have a feeling it's not supposed to be what I'm using. I need to be able to terminate the program after user inputs "0" using a while loop. Within main(), I tried adding a false conditional to the function
call within main():
askAgain = True
while askAgain == True:
getValidInput(selection = input("Select number 1, 2, 3. 0 exits program."))
if getValidInput(selection = input("Select number 1,2, 3. 0 exits program")) == "0"
askAgain == False
and I tried adding the while loop conditional within getValidInput(), instead of main():
askAgain = True
while askAgain == True:
if selection == "1":
askAgain == True
return print("message_1")
if selection == "0"
askAgain == False
return print("goodbye")
What am I doing wrong here? I know I'm not using the loop conditional correctly, but I've tried it several different ways. The sys.exit() is my backup. The user should be able to enter inputs until 0 is entered and that should be controlled from within main(). How can I use values inputted in getValidInput to change the value of my while loop conditional in main()?
If the program is required to run infinitely until the user inputs 0, your idea to use a boolean variable was already in a right path. However, you can utilize the getValidInput() function to return/assign whether the program should stop or continue running.
Assigning the variable selection in the function call inside the main() function is not needed.
One more tip is, you should be more careful on the brackets.
import sys
def getValidInput(selection):
if selection == "1":
print("message_1")
elif selection == "2":
print("message_2")
elif selection == "3":
print("message_3")
elif selection == "0":
print("goodbye")
else:
print("That is not a valid option.")
# Use this if-else block to determine whether your function should continue running or stop
if selection == '0':
return False
else:
return True
def main():
askAgain = True
while askAgain == True:
askAgain = getValidInput(input("Select number 1, 2, 3. 0 exits program."))
if __name__ == "__main__":
main()
You don't need to have the while loop in your helper function. Your helper function is supposed to do one thing, which is just to check the answer and do something.
What you can do is instead of system.exit, each condition return a bool value and pass it to askAgain.
askAgain = getValidateInput()
Finally a small thing, to follow PEP8 rule, you should use snake case: so asg_again, get_validate_input instead.
I want to produce an endless loop that would to different things depending on some user input.
When the .py is executed the loop starts and does some 'main' programm and the input window opens for the user. When typing 'alt1' the loop jumps in to the function 'main_alt1' and so on.
user_input = 'main'
user_input = input()
while True:
if user_input == 'main'
main()
elif user_input == 'alt1'
main_alt1()
elif user_input == 'exit'
exit()
The problem here is that the input is either given once before the loop (like in the example) or it stops the loop when the input is inside the loop until the input is given.
Does anyone has a smart way to do something like that. It doesn't need to be with input().
I think it's better to use a class to process the user input:
(I updated the code with the process method)
from multiprocessing import Process
from time import sleep
class InvalidAction(Exception):
pass
class Cmd:
def __init__(self):
self._active_thread = None
def _action_hi(self):
while True:
print('Hi!')
sleep(1)
def _action_ping(self):
while True:
print('Pong!')
sleep(1)
#staticmethod
def _get_method_name(action):
return f'_action_{action}'
def process(self, action: str):
method_name = self._get_method_name(action)
if not hasattr(self, method_name):
raise InvalidAction
if self._active_thread is not None:
self._active_thread.terminate()
self._active_thread = Process(target = getattr(self, method_name, None))
self._active_thread.start()
def main():
cmd = Cmd()
while True:
try:
user_input = input('Action: ')
cmd.process(user_input)
except InvalidAction as e:
print(f'Invalid Action!')
except KeyboardInterrupt:
print('Exiting the loop.')
break
except Exception as e:
print(f'Something went wrong - {e}')
if __name__ == '__main__':
main()
user_input = 'main'
user_input = input()
while True:
if user_input == 'main'
main()
elif user_input == 'alt1'
main_alt1()
elif user_input == 'exit'
exit()
user_input = input()
Taking the the input again at the end of loop works. Since it is while True it runs infinitely till user enters exit
after calling every function you can again take update from user to change variable
import keyboard
while True:
if keyboard.read_key() == 'a':
main_alt1()
elif keyboard.read_key() == 'b':
main_alt2()
elif keyboard.read_key() == 'e':
exit()
else:
main()
I want to have a loop running that will print "Hello" and when I press "K" it stops printing but it doesn't end the program, then when I press "K" again it starts printing again.
I tried this(using the keyboard module):
import keyboard
running = True
while running == True:
print("hello")
if keyboard.is_pressed("k"):
if running == True:
running = False
else:
running = True
but when I press the button it just ends the program and that's not what I'm trying to do. I understand why it ends but I don't know how to make it not end. How can I do that?
import keyboard
running = True
display = True
block = False
while running:
if keyboard.is_pressed("k"):
if block == False:
display = not display
block = True
else:
block = False
if display:
print("hello")
else:
print("not")
Maybe something like that:
import keyboard
running = True
stop = False
while !stop:
if keyboard.is_pressed("k"):
running = !running # Stops "hello" while
if keyboard.is_pressed("q"):
stop = !stop # Stops general while
if running:
print("hello")
You could use a handler for the keypress, which sets an event that the main thread can then test for periodically, and wait if required.
(Note that there are two types of events here, the keypress event and the setting of the running, so these should not be confused.)
from threading import Event
from time import sleep
import keyboard
hotkey = 'k'
running = Event()
running.set() # at the start, it is running
def handle_key_event(event):
if event.event_type == 'down':
# toggle value of 'running'
if running.is_set():
running.clear()
else:
running.set()
# make it so that handle_key_event is called when k is pressed; this will
# be in a separate thread from the main execution
keyboard.hook_key(hotkey, handle_key_event)
while True:
if not running.is_set():
running.wait() # wait until running is set
sleep(0.1)
print('hello')
import sys
import keyboard
from time import sleep
running = True
while running:
if keyboard.is_pressed("k"):
sleep(1)
elif keyboard.is_presed('Esc'):
sys.exit()
else:
print("hello")
I didnt test it, so please give me feedback
I think the right way is flushing the buffer, because the previous solutions may print more. This works for windows, for Linux, you should refer to Python read a single character from the user
import time
import subprocess
import sys
import msvcrt
printing = True
while (1):
# Try to flush the buffer
while not msvcrt.kbhit() and printing:
print("hello")
doit = msvcrt.getch().decode('utf-8')
if doit=="k":
printing = not printing
print("stop/start")
if doit == 'q':
break
This is the output of this code:
Please note that, if you add print("stop/start") in Adrian Melon's program, you can see his program prints several time "hello" after 'k' is pressed until the buffer will be empty.
import keyboard
running = True
display = True
block = False
while running:
if keyboard.is_pressed("k"):
print("stop/start")
if block == False:
display = not display
block = True
else:
block = False
if display:
print("hello")
else:
pass
This is the output of #Adrian-Melon program:
import keyboard
running = True
display = True
block = False
while running:
if keyboard.is_pressed("space"):
if block == False:
display = not display
block = True
else:
block = False
if display:
print("hello")
else:
input("Press Enter to continue...")
if block == False:
display = not display
block = True
You can use this to stop and start again.
I'm trying to design a control interface for my system which sends and receives some data through serial link. My searches related to GUI design took me to understand the "multi-threading" issue and code below shows the latest position I arrived.
This indicates similar parts (e.g try, run) with the ones I've seen on example GUIs. I planned to convert this to a GUI, once I understand how it exactly works.
So the problem is after I start, stop the code below I can't restart it again. Because, as I understand, multi-threading features only one cycle: start, stop and quit. I mean it doesn't accept start command after stop.
My question is how I can make this code to accept start after stopping?
Best wishes
import threading, random, time
class process(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
self.leave = 0
print("\n it's running ...\n\n")
while self.leave != 1:
print "Done!"
time.sleep(1)
operate = process()
while True:
inputt = input(" START : 1 \n STOP\t : 0 \n QUIT\t : 2 \n")
try:
if int(inputt) == 1:
operate.start()
elif int(inputt) == 0:
operate.leave = 1
elif int(inputt) == 2:
break
except:
print(" Wrong input, try egain...\n")
Create process inside while True loop
if int(inputt) == 1:
operate = process()
operate.start()
It should work.
... but your code may need other changes to make it safer - you will have to check if process exists before you try to stop it. You could use operate = None to control it.
import threading
import random
import time
class Process(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
self.leave = False
print("\n it's running ...\n\n")
while self.leave == False:
print("Done!")
time.sleep(1)
operate = None
while True:
inputt = input(" START : 1 \n STOP\t : 0 \n QUIT\t : 2 \n")
try:
if int(inputt) == 1:
if operate is None:
operate = Process()
operate.start()
elif int(inputt) == 0:
if operate is not None:
operate.leave = True
operate.join() # wait on process end
operate = None
elif int(inputt) == 2:
if operate is not None:
operate.leave = True
operate.join() # wait on process end
break
except:
print(" Wrong input, try egain...\n")
Other method is not to leave run() when you set leave = True but keep running thead. You would need two loops.
def run(self):
self.leave = False
self.stoped = False
print("\n it's running ...\n\n")
while self.leave == False:
while self.stoped == False:
print("Done!")
time.sleep(1)
Python beginner here. Sorry if it's a basic python concept
over = False
def run():
user_input = input("Over? (y/n): ")
if(user_input == 'y'):
over = True
while not over:
run()
Although the input is 'y' the loop doesn't stop.
You need to write global over, so function run() will change global variable
over = False
def run():
global over
user_input = input("Over? (y/n): ")
if(user_input == 'y'):
over = True
while not over:
run()
You shouldn't be using a global variable here. Return a boolean, and call run as the condition of the loop. (At this point, you may want to reconsider the name run as well.)
def run():
user_input = input("Over? (y/n)")
return user_input == 'y'
while run():
...
You are setting the local variable over inside the function run(), but you aren't passing it out to the scope from which it was called. Instead return the value to the calling scope like this:
over = False
def run():
user_input = input("Over? (y/n): ")
if(user_input == 'y'):
over = True
else:
over = False
return over
while not over:
over = run()