specific thread exit in python - python

I am using a thread to create an interruptible, which sends the KeyboardInterrupt command when a specific key is pressed. After this process I again use the msvcrt.getch() function. the problem is that the thread won't exit until I have pressed the key once. Ie the countdown function finishes but the the thread is still waiting for the input for the msvcrt.getch() function.
I tried putting exit.thread() at the end of the countdown function, but that exited the main thread. Do I need to use threading instead of thread?
import time, thread, msvcrt
print "enter time for timer"
n=raw_input()
def input_thread():
z=msvcrt.getch()
if z == "a" :
thread.interrupt_main()
if z != "a" :
thread.start_new_thread(input_thread, ())
print "nope"
thread.exit()
def countdown(n):
try:
thread.start_new_thread(input_thread, ())
for i in range(int(n)):
c = int(n) - int(i)
print c ,'seconds left','\r',
time.sleep(1)
except KeyboardInterrupt:
print "I was rudly interrupted"
countdown(n)
print """
"""
k=msvcrt.getch()
if k == "k" :
print "you typed k"
else :
print "you did not type K"

It is not the most beautiful way, but it works.
from concurrent.futures import thread
import threading
import time, msvcrt
print("enter time for timer")
n=input()
def input_thread():
z=msvcrt.getch()
if z == "a" :
thread.interrupt_main()
if z != "a" :
thread.start_new_thread(input_thread, ())
print ("nope")
thread.exit()
def countdown(n):
try:
threading.Thread(target=input_thread)
for i in range(int(n)):
c = int(n) - int(i)
print (c ,'seconds left','\r')
time.sleep(1)
except KeyboardInterrupt:
print("I was rudly interrupted")
countdown(n)
print ("")
k=msvcrt.getch()
if k == "k" :
print("you typed k")
else :
print ("you did not type K")

Related

How to ask Question by if statement via timeout

is there any way for ask question by if statement and after afew sec if user didnot give any answer , if state use a default answer?
inp = input("change music(1) or close the app(2)")
if inp = '1':
print("Music changed)
elif inp = '2':
print("good by")
in this case if user dont give any answer after 30 sec by default if statement choose number 3
from threading import Timer
out_of_time = False
def time_ran_out():
print ('You didn\'t answer in time') # Default answer
out_of_time = True
seconds = 5 # waiting time in seconds
t = Timer(seconds,time_ran_out)
t.start()
inp = input("change music(1) or close the app(2):\n")
if inp != None and not out_of_time:
if inp == '1':
print("Music changed")
elif inp == '2':
print("good by")
else:
print ("Wrong input")
t.cancel()
Timer Objects
This class represents an action that should be run only after a certain amount of time has passed — a timer. Timer is a
subclass of Thread and as such also functions as an example of
creating custom threads.
Timers are started, as with threads, by calling their start() method.
The timer can be stopped (before its action has begun) by calling the
cancel() method. The interval the timer will wait before executing its
action may not be exactly the same as the interval specified by the
user.
For example:
def hello():
print("hello, world")
t = Timer(30.0, hello)
t.start() # after 30 seconds, "hello, world" will be printed
class threading.Timer(interval, function, args=None, kwargs=None)
Create a timer that will run function with arguments args and keyword
arguments kwargs, after interval seconds have passed. If args is None
(the default) then an empty list will be used. If kwargs is None (the
default) then an empty dict will be used.
cancel()
Stop the timer, and cancel the execution of the timer’s action. This will only work if the timer is still in its waiting
stage.
Here's an alternative way to do it (python 3), using multiprocessing. Note, to get the stdin to work in the child process, you have to re open it first. I'm also converting the input from string to int to use with the multiprocessing value, so you might want to error check there as well.
import multiprocessing as mp
import time
import sys
import os
TIMEOUT = 10
DEFAULT = 3
def get_input(resp: mp.Value, fn):
sys.stdin = os.fdopen(fn)
v = input('change music(1) or close the app (2)')
try:
resp.value = int(v)
except ValueError:
pass # bad input, maybe print error message, try again in loop.
# could also use another mp.Value to signal main to restart the timer
if __name__ == '__main__':
now = time.time()
end = now + TIMEOUT
inp = 0
resp = mp.Value('i', 0)
fn = sys.stdin.fileno()
p = mp.Process(name='Get Input', target=get_input, args=(resp, fn))
p.start()
while True:
t = end - time.time()
print('Checking for timeout: Time = {:.2f}, Resp = {}'.format(t, resp.value))
if t <= 0:
print('Timeout occurred')
p.terminate()
inp = DEFAULT
break
elif resp.value > 0:
print('Response received:', resp.value)
inp = resp.value
break
else:
time.sleep(1)
print()
if inp == 1:
print('Music Changed')
elif inp == 2:
print('Good Bye')
else:
print('Other value:', inp)

raw_input with Main thread and concurrent thread in Python

I am working on a Python scripts that kicks off a thread with a loop and a raw_input so that user can enter commands. After this thread starts, main program starts a loop with another raw_input so that the user can enter commands.
How can this be organized so that the commands being inputted via console goes to the correct raw_input (main thread/concurrent thread)? At the moment, all inputs in the console are going to the main thread only.
Thanks
Example
import threading
def commThread():
while True:
chatAcceptance = raw_input("User")
t1 = threading.Thread(target=commThread)
t1.start()
while True:
userInput = raw_input("\nPlease insert a command:\n")
So this can be done via lock. I did a small code example that shows how to swap between one "scope" to the other using the raw_input.
import threading
lock = threading.Lock()
def inputReader(thread, prompt):
userInput = raw_input(prompt)
print thread + " " + userInput + "\n"
return userInput
def myThread1():
global lock
while True:
lock.acquire()
print "thread 1 got the lock\n"
while True:
threadInput = inputReader("thread 1", "from thread 1\n")
if threadInput == "release":
lock.release()
print "thread 1 released the lock\n"
break
def myThread2():
global lock
while True:
lock.acquire()
print "thread 2 got the lock\n"
while True:
threadInput = inputReader("thread 2", "from thread 2\n")
if threadInput == "release":
lock.release()
print "thread 2 released the lock\n"
break
t1 = threading.Thread(target=myThread1).start()
t2 = threading.Thread(target=myThread2).start()

Interrupt python script with a specific key on Linux

I'm trying to have a loop which increments and prints a value. While it's running I would like to press a key (eg. space or shift) and have it print that the key was pressed. Below is example code of what I would like.
def space():
print 'You pressed space'
def shift():
print 'You pressed shift'
x = 0
while True:
print(x)
#if space is pressed
space()
#if shift is pressed
shift()
x = x + 1;
time.sleep(1)
EDIT: Here is an example output
0
1
2
You pressed shift
3
4
5
You pressed space
6
7
.
.
.
I can help you with modified answer form here:
https://stackoverflow.com/questions/11918999/key-listeners-in-python
and for only space and enter:
import contextlib
import sys
import termios
import time
#contextlib.contextmanager
def raw_mode(file):
old_attrs = termios.tcgetattr(file.fileno())
new_attrs = old_attrs[:]
new_attrs[3] = new_attrs[3] & ~(termios.ECHO | termios.ICANON)
try:
termios.tcsetattr(file.fileno(), termios.TCSADRAIN, new_attrs)
yield
finally:
termios.tcsetattr(file.fileno(), termios.TCSADRAIN, old_attrs)
def space(ch):
if ord(ch) == 32:
print 'You pressed space'
def enter(ch):
if ord(ch) == 10:
print 'You pressed enter'
def main():
print 'exit with ^C or ^D'
with raw_mode(sys.stdin):
try:
x = 0
while True:
print(x)
ch = sys.stdin.read(1)
space(ch)
enter(ch)
x = x + 1;
time.sleep(1)
except (KeyboardInterrupt, EOFError):
pass
if __name__ == '__main__':
main()
If you're on windows, check out msvcrt:
import msvcrt
while True:
x += 1
sleep(x)
if msvcrt.kbhit():
print "You pressed: %s" % msvcrt.getch()

Countdown loop for a 'raw_input' on the same line in Python

I want to do a countdown loop for a normal raw_input were the normal raw_input don't change, only the numbers (in raw_input).
So, Do you want to try again? [15-1] outputs on one line and the numbers only change.
This is what I have so far and it doesn't work. So how would I do this?
while True:
for i in range(15,-1,-1):
con1=raw_input("\n Do you want to try again? " + str(i,))
if i == 0:
print "\n Thanks for playing!"
exit(0)
elif con1 == "no":
print "\n Thanks for playing!"
time.sleep(3)
exit(0)
elif con1 == "yes":
break
Linux answer -- will not work on Windows
Python 3
import select
import sys
def has_input(timeout=0.0):
return select.select([sys.stdin], [], [], timeout)[0]
def getans(timeout=15):
i = timeout
max_num_length = len(str(timeout))
while i:
print("\rDo you want to try again? {:{}} ".format(i, max_num_length),
end="", flush=True)
i -= 1
if has_input(1):
return input()
print()
return None
print(getans())
Python 2
import select
import sys
def has_input(timeout=0.0):
return select.select([sys.stdin], [], [], timeout)[0]
def getans(timeout=15):
i = timeout
max_num_length = len(str(timeout))
while i:
sys.stdout.write("\rDo you want to try again? {:{}} ".format(i, max_num_length))
sys.stdout.flush()
i -= 1
if has_input(1):
return raw_input()
print
return None
print getans(5)
getans will return None on timeout, or the response otherwise. Theoretically, if a Windows version of has_input could be implemented, this could work on Windows, but I haven't tested that.

initialization problem in Python

The error is given at the end:
from brisa.core.reactors import install_default_reactor
reactor = install_default_reactor()
print reactor
from brisa.upnp.control_point.control_point import ControlPoint
def on_new_device(dev):
print 'Got new device:', dev.udn
print "Type 'list' to see the whole list"
if not dev:
return
def create_control_point():
c = ControlPoint()
print "hello"
c.subscribe('new_device_event', on_new_device)
print "c"
return c
def main():
print "Inside main"
c = create_control_point()
print "Inside create control point"
c.start()
reactor.add_after_stop_func(c.stop)
reactor.main()
def _search(c):
""" Start searching for devices of type upnp:rootdevice and repeat
search every 600 seconds (UPnP default)
"""
c.start_search(600, 'upnp:rootdevice')
def _stop(c):
""" Stop searching
"""
c.stop_search()
def _list_devices(c):
""" Lists the devices that are in network.
"""
k = 0
for d in c.get_devices().values():
print 'Device no.:', k
print 'UDN:', d.udn
print 'Name:', d.friendly_name
print 'Device type:', d.device_type
print 'Services:', d.services.keys() # Only print services name
print
k += 1
# Control the loop at _handle_cmds function
running_handle_cmds = True
commands = {
'search': _search,
'stop': _stop,
'list': _list_devices,
}
def _handle_cmds(c):
while running_handle_cmds:
try:
input = raw_input('>>> ').strip()
if len(input.split(" ")) > 0:
try:
if len(input.split(" ")) > 1:
commands[input.split(" ")[0]](c, input.split(" ")[1])
else:
commands[input.split(" ")[0]](c)
except KeyError, IndexError:
print 'Invalid command, try help'
except TypeError:
print 'Wrong usage, try help to see'
except KeyboardInterrupt, EOFError:
c.stop()
break
# Stops the main loop
reactor.main_quit()
if __name__ == '__main__':
print "hello"
main()
Error:
ankit#ubuntu:~/Desktop$ python controlpt.py
<brisa.core.reactors.glib2.GLib2Reactor object at 0x965bdcc>
hello
Inside main
After that I know understand, it is not initialising the control point. The Information about the libraries(Control point) is available at http://brisa.garage.maemo.org/apidoc/index.html
If this is anything like some other event-based libraries such as Twisted, you want to get the reactor's main running before you do much of anything else.
Drop the call to reactor.main in your main function. Then, instead of just calling main in your if at the bottom, do this:
if __name__ == "__main__":
run_async_function(main)
reactor.main()
See if things behave more like what you expect then.
(run_async_function is in the threaded_call module.)

Categories