Python force input to stop program from hanging - python

Imagine I had this:
#file main.py
while alive:
msg = input()
print(msg)
Now in another thread I evaluate either if 'alive' is True or False.
The problem is input() will keep the program hanging.
Is there a way to force it to move on without user interacting with the program?
Or can I just terminate the whole program from inside the other thread?

Related

Python - Checking if there is an input from user without stopping the loop

I have a small script where I have a continuous loop. The loop runs and I expect that the user will give an input whenever he wants. I want to check if the user wrote something in the console, if yes, I will do something extra, if not, the loop continues.
The problem is that when I call the input() function, the program waits for user input.
The code that I will use here will be just a simple version of my code to show better what is my problem.
i=0
while True:
i+=1
if 'user wrote a number':
i+= 'user's input'
The objective is to not stop the loop if the user do not input anything. I believe this is a simple thing but I didn't find an answer for this problem.
Thank you for your time!
You can execute the background task (the while True) on a separate thread, and let the main thread handle the input.
import time
import threading
import sys
def background():
while True:
time.sleep(3)
print('background task')
def handling_input(inp):
print('Got {}'.format(inp))
t = threading.Thread(target=background)
t.daemon = True
t.start()
while True:
inp = input()
handling_input(inp)
if inp == 'q':
print('quitting')
sys.exit()
Sample execution (lines starting with >> are my inputs):
background task
>> a
Got a
>> b
Got b
background task
>> cc
Got cc
background task
background task
>> q
Got q
quitting
Process finished with exit code 0
The only caveat is if the user takes longer than 3 seconds to type (or whatever the value of time.sleep in background is) the input value will be truncated.
I'm don't think you can do that in one single process input(), because Python is a synchronous programming languaje,the execution will be stoped until input() receives a value.
As a final solution I'd recommend you to try implement your functions with parallel processing so that both 'functions' (input and loop) can get executed at the same time, then when the input function gets it's results, it sends the result to the other process (the loop) and finish the execution.

How do I abort reading a user's input in Python 3.x?

I have a thread that monitors user input which looks like this:
def keyboard_monitor(temp): #temp is sys.stdin
global flag_exit
while True:
keyin = temp.readline().rstrip().lower()
if keyin == "exit":
flag_exit = True
print("Stopping...")
if flag_exit == True:
break
If I type exit the flag is properly set and all the other threads terminate. If another one of my threads sets the flag, this thread refuses to finish because it's hanging on the user input. I have to input something to get it to finish. How do I change this code so that the program finishes when the flag is set externally?
Its hard to tell exactly what is going wrong without more of your code, but as an easy solution you could rather exit() which is a python built in. This should reliably terminate the application, also sys.exit()
From wim's comment:
You can use the atexit module to register clean up handlers
import atexit
def cleanup():
pass
# TODO cleanup
atexit.register(cleanup)

Writing to console of parent process os.kill

I have a program that includes a -p --pause flag with values 1 for pause and 2 for resume. The purpose of this is to allow a user to specifically pause the program (it's intended to run as a daemon) manually. Functionally, it works (it pauses and resumes when need be...the kill function also works, though is unrelated to this question now that I look at my code) but I can't get my messages to show up. Basically I would like the original parent program to let print to console when it is being paused or resumed from another place. I think this can be done with signals, but I'm not really sure how this is done, especially in Python (just learning it)
Thanks!
if __Kill:
os.system("kill %s" % old_pid)
sys.exit()
if int(__Pause) == 1:
pause_proc(old_pid)
elif int( __Pause) == 2:
resume_proc(old_pid)
def pause_proc(pid):
print "Pausing Procedure"
os.kill(pid, signal.SIGSTOP)
def resume_proc(pid):
os.kill(pid, signal.SIGCONT)
print "Resuming Procedure"

Python/Calling python scripts within bash terminal: What exactly happens when user presses Ctrl-C?

I need help with controlling a python script. I want to run a script that controls two robots. A routine consists of a series of motions which either move the arm or move the gripper. The form of the code is as follows:
def robot_exec():
# List of robot arm poses:
*many_many_lines_of_position_vectors*
# List of robot gripper poses:
*open position*
*close position*
while 1:
*Call a function that moves the robot arm(s) to a position on the list*
*Call a function that moves the robot gripper(s) to a position on the list*
*continue calling functions many times until the desired routine is complete*
n = raw_input("Restart the routine? (Y/N)")
if n.strip() == 'n' or 'N':
break
elif n.strip() == 'y' or 'Y':
continue
else:
print "Invalid input. Exiting..."
break
If the routine is complete (i.e. every function was called), it asks if I want to restart, and if I choose yes, behaves as normal, which is good.
But, if I press ctrl-C in the middle of the routine, the message "Restart the routine?" still pops up and asks for input, and I don't want that. What I want is either one of the following:
if and only if the user presses ctrl-C, completely exit everything, no questions asked.
if and only if the user presses ctrl-C, return the robots to home position (defined in that list of arm poses) and then completely exit everything.
My main question is, how does ctrl-C actually work? I thought it would just exit the script but in actuality it still prints stuff and asks for input. A subset of that broad question is, how can I just get the desired behavior (completely exit everything when pressing ctrl-C)?
I realize this is a clunky way of doing what I need the robots to do, but it is the best way I can think of with my limited knowledge of python.
Thank you,
-Adrian
The comments/answers about signals are technically correct (on UNIX), but in Python the CTRL+C handling is neatly wrapped away from you. What happens in a Python program is that at the point where you press CTRL+C, a KeyboardInterrupt exception is raised.
Now, your problem seems to be in the code that you have removed from the listing, i.e., in the "calling robot routines" part. That code catches the KeyboardInterrupt.
I guess either your code or library code that you call does something like:
try:
# some long running code
# ...
except:
# something, or just pass
Note the naked except:. Naked excepts are almost always a bad thing. Instead you or the library should do:
try:
# some long running code
# ...
except Exception:
# something to fix the situation
Using except Exception: does not catch the KeyboardInterrupt exception, which will let you handle it appropriately, or just let the program exit. Have a look at the Exception class hierarchy.
What exactly happens when user presses Ctrl-C?
A signal is raised.
how can I just get the desired behavior
>>> import signal
>>> def handler(sig, stack_frame):
... print "Handled"
...
>>> signal.signal(signal.SIGINT, handler)
<built-in function default_int_handler>
^C # <--- typed ctrl-c here
>>> Handled
See the doc of signal for details.
Please note: on Linux I use signal.SIGINT. On Windows, maybe it is signal.CTRL_C_EVENT instead.
you can handle Ctrl_C with this code :
#!/usr/bin/env python
import signal
import sys
def signal_handler(signal, frame):
#write your command here for example i write print below :
print('You pressed Ctrl+C!')
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
print('Press Ctrl+C')
signal.pause()

run a python program on a new thread

I have two programs
program1.py is like commandline interface which takes command from user
program2.py has the program which runs the relevant program as per the command.
Program 1 has also has an quit_program() module
In our simple universe.. lets say I have just one command and just one program
So lets say...
program1.py
def main():
while True:
try:
command = raw_input('> ')
if command == "quit" :
return
if command == '':
continue
except KeyboardInterrupt:
exit()
parseCommand(command)
And then I have:
if commmand == "hi":
say_hi()
Now program2 has
def say_hi():
#do something..
Now there can be two cases...
Either say_hi() completes in which case no issue...
But what i want is that if user enters a command (say: end)
then this say_hi() is terminated in between..
But my current implementation is very sequential.. I mean I dont get to type anything on my terminal untill the execution is completed..
Somethng tells me that the say_hi() should be running on another thread?
I am not able to think straight about this.
Any suggestions?
Thanks
The threading module is what you are looking for.
import threading
t = threading.Thread(target=target_function,name=name,args=(args))
t.daemon = True
t.start()
The .daemon option makes it so you don't have to explicitly kill threads when your app exits... Threads can be quite nasty otherwise
Specific to this question and the question in the comments, the say_hi function can be called in another thread as such:
import threading
if commmand == "hi":
t = threading.Thread(target=say_hi, name='Saying hi') #< Note that I did not actually call the function, but instead sent it as a parameter
t.daemon = True
t.start() #< This actually starts the thread execution in the background
As a side note, you must make sure you are using thread safe functions inside of threads. In the example of saying hi, you would want to use the logging module instead of print()
import logging
logging.info('I am saying hi in a thread-safe manner')
You can read more in the Python Docs.

Categories

Resources