Input without stopping program - python

I am trying to make a countdown timer that prints the time remaining, and when you input something, it prints what you inputted. My problem is I don't want to wait for the input, just keep running the timer. My incorrect code:
timer = 100
while True:
print(timer)
timer -= 1
if input('> '):
print('the output of input')
You could say I want to have the timer printing the time in the background.

Here's a function that will timeout if no input is given:
import select
import sys
def timeout_input(timeout, prompt="", timeout_value=None):
sys.stdout.write(prompt)
sys.stdout.flush()
ready, _, _ = select.select([sys.stdin], [], [], timeout)
if ready:
return sys.stdin.readline().rstrip('\n')
else:
sys.stdout.write('\n')
sys.stdout.flush()
return timeout_value
You can easily modify it so it shows the remaining time by changing the timeout value on select.select to 1, and looping timeout times.

Standard input and standard output (accessed via input() and print()) are not a good choice for writing interactive asynchronous user interface (UI). Python support a few UIs via it's standard library. For example, curses is a text based user interface available on many POSIX systems. Here is an exmaple code for showing a countdown timer while accepting a number from the user:
import time
import curses
def get_number(seconds):
def _get_number(stdscr):
stdscr.clear()
timeout = time.time() + seconds
s = ""
while time.time() <= timeout:
time_left = int(timeout - time.time())
stdscr.addstr(0, 0, 'Countdown: {} {}'.format(time_left,
"*" * time_left + " " * seconds))
stdscr.addstr(2, 0, ' ' * 50)
stdscr.addstr(2, 0, 'Your Input: {}'.format(s))
stdscr.refresh()
stdscr.timeout(100)
code = stdscr.getch()
stdscr.addstr(10, 0, 'Code: {}'.format(code)) # for debug only
stdscr.refresh()
if ord("0") <= code <= ord("9"):
s += chr(code)
continue
if code == 10 and s: # newline
return int(s)
if code == 127: # backspace
s = s[:-1]
return curses.wrapper(_get_number)
print(get_number(10))

Related

Is there anyway to add a Defusal Sequence whilst a countdown is happening

I am attempting to program a defusable bomb for a csgo prop and was trying to make it as close as i can to the original thing. I have got everything working smoothly. An entry code and a Timer. The only thing I need to do is add a defusable section to it. Whilst the Bombs timer is running I would need to be able to cancel that action with an Input Code. Where, and what would I put?
I have tried doing a
defuse = input("Defusal Code")
if defuse == "7355608":
break
import time
while True:
uin = input("")
try:
when_to_stop = abs(int(uin))
except KeyboardInterrupt:
break
except:
print("NAN!")
while when_to_stop > 0:
s, ms = divmod(when_to_stop, 100)
m, s = divmod(s, 60)
time_left = str(m).zfill(2) + ":" + str(s).zfill(2) + ":" + str(ms).zfill(2)
print(time_left, end="\r")
time.sleep(0.01)
when_to_stop -=1
print()
print("BOMB DETONATED")

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)

Python - Detect input within a terminal screensaver

I'm writing a code that basically runs without a loop for the sake of mobility and functionality. Let's say that when I run the program I use the -i option to continue using the python interpreter as it loads every function written. The thing is that I'm using a screensaver like function after the program print some basic information to make it look not so boring.
My question is: How can I maintain the screen saver running without blocking the interpreter prompt. I already wrote how to handle keyboard input to stop it using curses "getch()". I tried using threading but with no avail as it doesn't detect any keyboard input so it keeps running.
Is there any way I can get around this? How can I detect any input without blocking therefore retaining the interpreter prompt?
Right know it detects an input and raise a KeyboardException captured to make the screensaver stop.
Thanks in advance
I'm using this code with some added modifications:
Matrix-Curses
What I have so far:
Completed Code
This are the modifications done to the code:
def clear(int=None):
""" Clear Terminal Screen """
from subprocess import call
call('clear')
if int == 0:
exit()
def Matrix():
steps = 0
global scr
curses.curs_set(0)
curses.noecho()
if USE_COLORS:
curses.start_color()
curses.use_default_colors()
curses.init_pair(COLOR_CHAR_NORMAL, curses.COLOR_GREEN, curses.COLOR_BLACK)
curses.init_pair(COLOR_CHAR_HIGHLIGHT, curses.COLOR_WHITE, curses.COLOR_GREEN)
curses.init_pair(COLOR_WINDOW, curses.COLOR_GREEN, curses.COLOR_GREEN)
height, width = scr.getmaxyx()
window_animation = None
lines = []
for i in range(DROPPING_CHARS):
l = FallingChar(width, MIN_SPEED, MAX_SPEED)
l.y = randint(0, height-2)
lines.append(l)
scr.refresh()
while True:
height, width = scr.getmaxyx()
for line in lines:
line.tick(scr, steps)
for i in range(RANDOM_CLEANUP):
x = randint(0, width-1)
y = randint(0, height-1)
scr.addstr(y, x, ' ')
if randint(0, WINDOW_CHANCE) == 1:
if window_animation is None:
#start window animation
line = random.choice(lines)
window_animation = WindowAnimation(line.x, line.y)
if not window_animation is None:
still_active = window_animation.tick(scr, steps)
if not still_active:
window_animation = None
scr.refresh()
time.sleep(SLEEP_MILLIS)
if SCREENSAVER_MODE:
key_pressed = scr.getch() != -1
if key_pressed:
raise KeyboardInterrupt
steps += 1
def ScreenSaver():
from time import sleep
from datetime import datetime as dt
global scr
TimeLimit = 10
StartTime = dt.now()
while True:
try:
sleep(1)
StopTime = (dt.now() - StartTime)
LastTime = StopTime.days*86400000 + StopTime.seconds*1000 + StopTime.microseconds/1000
if LastTime >= TimeLimit:
GetLocaleStatus = locale.getlocale()
locale.setlocale(locale.LC_ALL, '')
scr = curses.initscr()
scr.nodelay(1)
key_being_pressed = scr.getch() != -1
if not key_being_pressed:
try:
Matrix()
except KeyboardInterrupt:
TimeLimit = 30000
StartTime = dt.now()
raise KeyboardInterrupt
except KeyboardInterrupt:
curses.endwin()
curses.curs_set(1)
curses.reset_shell_mode()
curses.echo()
clear()
# return
main()

Pause and resume a running script in Python 3.42 in Windows

I'm new to Python and have been googling for a couple of days and read all I can find on this forum. Might be that I don't understand it all but I haven't found a solution to my problem yet. Ask for forgiveness already if there's an answer already to my problem, then I haven't understood it.
I want to make a Pause function for my program Tennismatch. The program will when it's being run print the score of a tennis match like this: "15-0, 15-15 etc ongoing till the match ends. It will print the score line by line.
I want the user to be able to pause after x number of balls, games, etc. So I don't know when the user wants to pause and after the user has paused I want the user to be able to resume the tennismatch where it was.
Have seen the time.sleep() but as I have understood it you must know when you want to pause to use this and it also ain't an indefinetie pause like I want. With input() it's the same.
Am going to make a GUI later on when the code is finished. Happy for anything that leads me to solving my problem.
I use Windows and Python 3.42 and run the program in Shell.
A piece of the code (haven't written it all yet, it's more of a general situation when something is being printed line after line for some time and want to be able do pause in the CIL:
#self.__points = [0,0]
def playGame(self):
if self.server == True: #self.server is either True or False when someone calls playGame()
server = self.player_1.get_win_serve() #self.player_1 = an object of a class Player():
else:
server = self.player_2.get_win_serve() #get_win_serve() method returns the probability to win his serv (1-0)
while (0 < self.__points[0] - self.__points[1] >= 2 or 0 < self.__points[1] - self.__points[0] >= 2) and (self.__points[1] >= 4 or self.__points[0] >= 4):
x = random.uniform(0,1)
if x > 0 and x < server:
self.__points[0] += 1
else:
self.__points[1] += 1
# print('The score, by calling a score() function that I haven't written yet')
For dealing with events in main loop you need to make a separated thread which capture input or any other event.
import sys
from sys import stdin
from time import sleep
from threading import Thread
from Queue import Queue, Empty
def do_something():
sleep(1)
print 42
def enqueue_output(queue):
while True:
# reading line from stdin and pushing to shared queue
input = stdin.readline()
print "got input ", input
queue.put(input)
queue = Queue()
t = Thread(target=enqueue_output, args=(queue,))
t.daemon = True
t.start()
pause = False
try:
while True:
try:
command = queue.get_nowait().strip()
print 'got from queue ', command
except Empty:
print "queue is empty"
command = None
if command:
if command == 'p':
pause = True
if command == 'u':
pause = False
if not pause:
print pause
do_something()
except KeyboardInterrupt:
sys.exit(0)
I came up with the following.
while True:
try:
## Keep doing something here
## your regular code
print '.',
except KeyboardInterrupt:
## write or call pause function which could be time.sleep()
print '\nPausing... (Hit ENTER to continue, type quit to exit.)'
try:
response = raw_input()
if response.lower() == 'quit':
break
print 'Quitting...'
except KeyboardInterrupt:
print 'Resuming...'
continue
The Event loop might as well be the code I wrote with.
I don't see any user input so I assume that x emulates it. To pause the game if x < 0.1 and to unpause(/resume) it if x > 0.9, you could:
while your_condition(self.__points):
x = random.random()
if x < 0.1: # pause
self.pause()
elif x > 0.9: # resume
self.resume()
if self.is_paused:
continue # do nothing else only wait for input (`x`)
# assume your_condition() has no side-effects
# here's what the resumed version does:
print("...")
# change self.__points, etc
where pause(), resume(), is_paused() methods could be implemented as:
def __init__(self):
self.is_paused = False
def pause(self):
self.is_paused = True
def resume(self):
self.is_paused = False
as you can see the implementation is very simple.

Python realtime timer

Could anybody advise me on converting the Java Timer class to Python? Currently I am converting a Java program to a Python script. However, Python does not have the Timer/TimerTask library (if it does have this, please enlighten me. Thanks!). I need to be able to reset the Timer. Java has Timer.cancel, but Python doesn't have this. Is there any replacement for it?
timer.cancel();
timer = new Timer("Printer");
MyTask t = new MyTask();
timer.schedule(t, 0, 1000);
Java script timer
class Timerclass extends TimerTask {
//times member represent calling times.
private int times = 0;
public void run() {
times++;
if (times <= 5) {
System.out.println(""+times);
} else {
this.cancel();
//Stop Timer.
System.out.println("Timer Finish");
}
}
}
Currently my code
import time
import threading
class Variable:
count = 0
people = 0
times = 0
def enter():
if int(Variable.count == 1):
print("Entered")
t = threading.Timer(5.0, countdown)
t.start()
else:
print("Entered +1")
t.clear() // Stuck Help
t = threading.Timer(5.0, countdown)
t.start()
def out():
if int(Variable.count > 0):
print("Exited")
elif int(Variable.count < 0):
print("Error")
def countdown():
print("TIMEUP")
while True:
sensor1 = input("Sensor 1: ")
sensor2 = input("Sensor 2: ")
Variable.count+=1
if int(sensor1) == int(sensor2):
Variable.count -= 1
print(Variable.count)
print("error")
elif int(sensor1) == 1:
Variable.people += 1
print(Variable.people)
enter()
elif int(sensor2) == 1:
Variable.people -= 1
print(Variable.people)
out()
else:
print("Error")
i have one problems that i'm stuck in i need to stop the current counting and start a new one whenever the method call
Basically what i want or im looking out for is when i recall this method it will reset or cancel any existing and recount again
Update latest
import time
import threading
class Variable:
count = 0
people = 0
times = 0
def countdown():
print("TIMEUP")
t = threading.Timer(5.0, countdown)
def enter():
if int(Variable.count == 1):
print("Entered")
t.start()
else:
print("Entered +1")
t.cancel()
t.join() # here you block the main thread until the timer is completely stopped
t.start()
def out():
if int(Variable.count > 0):
print("Exited")
elif int(Variable.count < 0):
print("Error")
while True:
sensor1 = input("Sensor 1: ")
sensor2 = input("Sensor 2: ")
Variable.count+=1
if int(sensor1) == int(sensor2):
Variable.count -= 1
print(Variable.count)
print("error")
elif int(sensor1) == 1:
Variable.people += 1
print(Variable.people)
enter()
elif int(sensor2) == 1:
Variable.people -= 1
print(Variable.people)
out()
else:
print("Error")
Anybody can spot my ,istake im getting this error but i t.clear() the process
in start raise RuntimeError("threads can only be started once")
RuntimeError: threads can only be started once
I would suggest using the time module for something like this:
from time import time, sleep
from datetime import datetime, timedelta
nowtime = time()
#Put your script here
x = 1
for k in range(1000):
x+=1
sleep(0.01)
sec = timedelta(seconds=int(time()-nowtime))
d = datetime(1,1,1)+sec
print("DAYS:HOURS:MIN:SEC")
print("%d:%d:%d:%d" % (d.day-1, d.hour, d.minute, d.second))
This assigns the time in seconds at the beginning to a variable, and after the main script has finished, it subtracts the previous time from the current time and formats it in days, hours, minutes, and seconds.
Here is it running:
bash-3.2$ python timing.py
DAYS:HOURS:MIN:SEC
0:0:0:10
bash-3.2$
You could also use the Threading module, which has a built-in cancel method:
>>> import threading
>>> def hello():
... print "This will print after a desired period of time"
...
>>> timer = threading.Timer(3.0, hello)
>>> timer.start() #After 3.0 seconds, "This will print after a desired period of time" will be printed
>>> This will print after a desired period of time
>>> timer.start()
>>> timer = threading.Timer(3.0, hello)
>>> timer.start()
>>> timer.cancel()
>>>
Python actually has a class for this, which includes a cancel method: threading.Timer. It seems to be close enough to the Java Timer class for your needs (The Java Timer also runs in background thread). Here's the example usage from the docs:
def hello():
print "hello, world"
t = Timer(30.0, hello)
t.start() # after 30 seconds, "hello, world" will be printed
Edit:
The problem with your updated code is that you're trying to use the same Timer object more than once. That may be possible in the Java implementation, but in Python you can't reuse a Thread object (Timer is a Thread subclass). You'll need to create a new Timer object after you join() it. Like this:
t = threading.Timer(5.0, countdown)
def enter():
global t # You need this to tell Python that you're going to change the global t variable. If you don't do this, using 't = ..' will just create a local t variable.
if int(Variable.count == 1):
print("Entered")
t.start()
else:
print("Entered +1")
t.cancel()
t.join() # here you block the main thread until the timer is completely stopped
t = threading.Timer(5.0, countdown)
t.start()

Categories