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()
Related
I am currently learning python and stuck on a coding exercise. I am trying to achieve the result as shown on the image1. I am stuck on the overall code. I also not sure how to incorporate the "quit", so that the program terminates.
Image1
def tester(result):
while tester:
if len(result)< 10:
return print(givenstring)
else:
return print(result)
def main():
givenstring = "too short"
result=input("Write something (quit ends): ")
if __name__ == "__main__":
main()
For your problem, you need to have a variable that is your Boolean (true/false) value and have your while loop reference that. currently your while loop is referencing your function. inside your main function when you get your user input you can have a check that if the input is "quit" or "end" and set you variable that is controlling your loop to false to get out of it.
you also are not calling your tester function from your main function.
You missed into main() function to call your function, like tester(result). But such basics should not be asked here.
def tester(result):
if len(result)< 10 and result != 'quit':
givenstring = "too short"
return print(givenstring)
else:
return print(result)
def main():
result=None
while True:
if result == 'quit':
print("Program ended")
break
else:
result=input("Write something (quit ends): ")
if result.lower() == 'quit':
result = result.lower()
tester(result.lower())
if __name__ == "__main__":
main()
The example code that I used
the main idea is when the user enters the wrong input, it will return a menu choice to let the user back to main_menu or continue
but when i want to enter data and choose back to main_menu and try to terminate it, the TenantID function still running
def TenantID():
while True:
error_list = []
tenant_id = str(input("1.Enter your Tenant ID: "))
if ValidateTenantID(tenant_id, error_list):
print(*error_list)
if MenuChoice() is True:
menu()
else:
continue
else:
break
return tenant_id
def MenuChoice():
Choice = input("\x1B[1m" + "Press M return to main menu or Any key
to continue: " + '\x1B[0m')
if Choice in ["M", "m"]:
return True
else:
return False
def ValidateTenantID(tenant_id, error_list):
returnValue = CheckLength(tenant_id)
if returnValue is True:
returnValue = CheckTenantID(tenant_id)
if returnValue is True:
returnValue = CheckDataIfExist(tenant_id)
if returnValue is not True:
error_list.append(returnValue)
else:
error_list.append(returnValue)
else:
error_list.append(returnValue)
return error_list
The problem
If you want to terminate from the menu function, then return from it and/or stop the loop that is running it.
For example,
running = True
def menu():
print('options...')
choice = input('> ')
if choice == '5':
global running
running = False
return # completely stop this function from doing other things
elif choice == '1':
tid = TenantID()
def TenantID():
valid = False
while not valid:
error_list = []
tenant_id = input("1.Enter your Tenant ID: ")
valid = ValidateTenantID(tenant_id, error_list)
print(*error_list)
if MenuChoice():
break
if not valid:
return None
else:
return tenant_id
while running: # can be changed from the menu function via global variable
menu()
print('bye')
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)
I'm creating part of a program right now for a personal project and I need some help on one aspect of it.
Here is how the program works:
User enters the amount of time to run
User enters the text - Files are modified
Timer is started
optional User can enter "password" to interrupt the timer
Actions are reversed
I have all of the steps coded except the Timer because I'm trying to figure out the best way to do this. Ideally, I'd like the timer to be displaying a countdown, and if the user enters a certain "password" the timer is interrupted and it skips to step number 5.
Would the best way to do this be with a thread? I haven't worked much with threads in the past. I just need someway for the timer to be displayed while also giving control back to the user in case they want to enter that password.
Thanks for any help you provide.
Here's the code:
import time
import urllib
import sys
def restore():
backup = open(r'...backupfile.txt','r')
text = open(r'...file.txt', 'w+')
text.seek(0)
for line in backup:
text.write(line)
backup.close()
text.close()
text = open(r'...file.txt', 'a+')
backup = open(r'...backupfile.txt','w+')
text.seek(0)
for line in text:
backup.write(line)
backup.close()
while True:
url = raw_input('Please enter a URL: ')
try:
if url[:7] != 'http://':
urllib.urlopen('http://' + url)
else:
urllib.urlopen(url)
except IOError:
print "Not a real URL"
continue
text.write(url)
while True:
choice = raw_input('Would you like to enter another url? (y/n): ')
try:
if choice == 'y' or choice == 'n':
break
except:
continue
if choice == 'y':
text.seek(2)
continue
elif choice == 'n':
while True:
choice = raw_input('Would you to restore your file to the original backup (y/n): ')
try:
if choice == 'y' or choice == 'n':
break
except:
continue
if choice == 'y':
text.close()
restore()
sys.exit('Your file has been restored')
else:
text.close()
sys.exit('Your file has been modified')
As you can see, I haven't added the timing part yet. It's pretty straight forward, just adding urls to a text file and then closing them. If the user wants the original file, reverse() is called.
Under Windows you can use msvcrt to ask for a key. Asking for a password is actually more complex, because you have to track several keys. This program stops with F1.
import time
import msvcrt
from threading import Thread
import threading
class worker(Thread):
def __init__(self,maxsec):
self._maxsec = maxsec
Thread.__init__(self)
self._stop = threading.Event()
def run(self):
i = 1
start = time.time()
while not self.stopped():
t = time.time()
dif = t-start
time.sleep(1) # you want to take this out later (implement progressbar)
# print something once in a while
if i%2==0: print '.',
#check key pressed
if msvcrt.kbhit():
if ord(msvcrt.getch()) == 59:
self.stop()
#do stuff
# timeout
if dif > self._maxsec:
break
i+=1
def stop(self):
print 'thread stopped'
self._stop.set()
def stopped(self):
return self._stop.isSet()
print 'number of seconds to run '
timeToRun = raw_input()
#input files
#not implemented
#run
w = worker(timeToRun)
w.run()
#reverse actions
How would I write a Python program that would always be looking for user input. I think I would want to have a variable equal to the input and then something different would happen based on what that variable equaled. So if the variable were "w" then it would execute a certain command and keep doing that until it received another input like "d" Then something different would happen but it wouldn't stop until you hit enter.
If you want to constantly look for an user input you'll need multithreading.
Example:
import threading
import queue
def console(q):
while 1:
cmd = input('> ')
q.put(cmd)
if cmd == 'quit':
break
def action_foo():
print('--> action foo')
def action_bar():
print('--> action bar')
def invalid_input():
print('---> Unknown command')
def main():
cmd_actions = {'foo': action_foo, 'bar': action_bar}
cmd_queue = queue.Queue()
dj = threading.Thread(target=console, args=(cmd_queue,))
dj.start()
while 1:
cmd = cmd_queue.get()
if cmd == 'quit':
break
action = cmd_actions.get(cmd, invalid_input)
action()
main()
As you'll see this, will get your messages a little mixed up, something like:
> foo
> --> action foo
bar
> --> action bar
cat
> --> Unknown command
quit
That's beacuse there are two threads writing to stdoutput at the same time. To sync them there's going to be need of lock:
import threading
import queue
def console(q, lock):
while 1:
input() # Afther pressing Enter you'll be in "input mode"
with lock:
cmd = input('> ')
q.put(cmd)
if cmd == 'quit':
break
def action_foo(lock):
with lock:
print('--> action foo')
# other actions
def action_bar(lock):
with lock:
print('--> action bar')
def invalid_input(lock):
with lock:
print('--> Unknown command')
def main():
cmd_actions = {'foo': action_foo, 'bar': action_bar}
cmd_queue = queue.Queue()
stdout_lock = threading.Lock()
dj = threading.Thread(target=console, args=(cmd_queue, stdout_lock))
dj.start()
while 1:
cmd = cmd_queue.get()
if cmd == 'quit':
break
action = cmd_actions.get(cmd, invalid_input)
action(stdout_lock)
main()
Ok, now it's better:
# press Enter
> foo
--> action foo
# press Enter
> bar
--> action bar
# press Enter
> cat
--> Unknown command
# press Enter
> quit
Notice that you'll need to press Enter before typing a command to enter in "input mode".
from http://www.swaroopch.com/notes/Python_en:Control_Flow
#!/usr/bin/python
# Filename: while.py
number = 23
running = True
while running:
guess = int(input('Enter an integer : '))
if guess == number:
print('Congratulations, you guessed it.')
running = False # this causes the while loop to stop
elif guess < number:
print('No, it is a little higher than that.')
else:
print('No, it is a little lower than that.')
else:
print('The while loop is over.')
# Do anything else you want to do here
print('Done')
Maybe select.select is what you are looking for, it checks if there's data ready to be read in a file descriptor so you can only read where it avoiding the need to interrupt the processing (well, in the example it waits one second but replace that 1 with 0 and it'll work perfectly):
import select
import sys
def times(f): # f: file descriptor
after = 0
while True:
changes = select.select([f], [], [], 1)
if f in changes[0]:
data = f.readline().strip()
if data == "q":
break
else:
print "After", after, "seconds you pressed", data
after += 1
times(sys.stdin)
if you want to get input repeatedly from user;
x=1
while x==1:
inp = input('get me an input:')
and based on inp you can perform any condition.
You can also use definitions, say, something like this:
def main():
(your main code)
main()
main()
though generally while loops are much cleaner and don't require global variables :)