EOF error while taking input using multiprocessing - python

I am making a stop watch in python which prints out the seconds passed and as soon as the user presses enter, it stops.
I am using multiprocessing to ask for an input and keep printing until an input is received. but the code is giving an EOF error for the input statement when I run it, what am I doing wrong?
import os
import multiprocessing
end = multiprocessing.Value('i',0)
def get_input(end):
x = input('')
end.value = 1
def print_time(end):
secs = 0
mins = 0
hrs = 0
x = input('start: ')
while True:
mins, secs = divmod(secs, 60)
hrs = 0
if mins > 60:
hrs, mins = divmod(mins, 60)
timer_display = '{:02d}:{:02d}:{:02d}'.format(hrs, mins, secs)
print(timer_display)
if end.value == 1:
break
time.sleep(1)
secs += 1
if __name__ == "__main__":
func1 = multiprocessing.Process(target = get_input, args = (end,))
func2 = multiprocessing.Process(target = print_time, args = (end,))
func1.start()
func2.start()
func1.join()
func2.join()

It's probably better to start/stop the stopwatch in the main program and just use one Process to display the timer. Something like this:
from multiprocessing import Process, Value
import time
def showTime(end):
start = time.time()
while end.value == 0:
elapsed = int(time.time() - start)
ss = elapsed % 60
mm = elapsed // 60 % 60
hh = elapsed // 3600
print(f'{hh:02d}:{mm:02d}:{ss:02d}')
time.sleep(1)
def main():
input('Press enter to start: ')
end = Value('i', 0)
Process(target=showTime, args=(end,)).start()
input('Press enter to stop: ')
end.value = 1
if __name__ == '__main__':
main()
Also, this technique allows for any potential drift due to processing time

Related

How do I iterate through a countdown timer while checking for user input simultaneously?

I am trying to code a chess timer in which there are two timers counting down alternatingly. Only one timer runs at a time, and when a certain input is given by the user, which I am using keyboard.is_pressed("some_key") for, one timer pauses and the other begins counting down and vice versa. My problem is that to countdown by intervals of 1 second, I am using time.sleep(1) and the program will not receive user input during this time, so unless the user gives input on exactly the 1 second mark, nothing happens. How can I make the countdown process and the checking for user input process run at the same time?
Here is the code:
import time
import keyboard
def timers(t1, t2):
pause = True
while t1 or t2:
if pause:
while pause:
mins1 = t1 // 60
secs1 = t1 % 60
timer1 = '{:02d}:{:02d}'.format(mins1, secs1)
print("Timer1: ", timer1)
time.sleep(1)
t1 -= 1
if keyboard.is_pressed("w"):
pause = False
break
else:
continue
else:
while not pause:
mins2 = t2 // 60
secs2 = t2 % 60
timer2 = '{:02d}:{:02d}'.format(mins2, secs2)
print("Timer2: ", timer2)
time.sleep(1)
t2 -= 1
if keyboard.is_pressed("w"):
pause = True
break
print("Beep")
tWhite = int(input("Enter the time in seconds for White: "))
tBlack = int(input("Enter the time in seconds for Black: "))
timers(tWhite, tBlack)

Run these two sections at once Python

I have some Python for a Raspberry Pi where I test for a button press (first loop) and use it to start and stop a timer (second loop). However, if I run this program only the first loop in the sequence runs. How can I make it so both run at the same time? Code:
EDIT: made changes to code in attempt to accommodate threading. Would this work?
import os
os.chdir('/home/pi/Desktop/Python')
import lcd
lcd.lcd_init()
import time
import threading
from threading import Thread
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(23,GPIO.IN, pull_up_down=GPIO.PUD_UP)
latest_state = None
status = False
seconds = 0
minutes = 0
hours = 0
def button():
while True:
if status == True:
seconds +=1
if seconds == 59:
seconds = 0
minutes = minutes + 1
if minutes == 59:
minutes = 0
hours = hours + 1
tup = " H:",hours," M:",minutes," S:",seconds
display = ''.join(map(str, tup))
lcd.lcd_string(display,2)
time.sleep(0.99)
Thread(target = button).start()
while True:
inputValue = GPIO.input(23)
if inputValue != latest_state:
latest_state = inputValue
if latest_state:
print " "
else:
status = not status
print status
print " "

Stopping Stopwatches

I am trying to create a stopwatch that starts and stops through the user pressing the enter. Once to start and again to stop. The start works perfectly but the stopping section is not working. I've tried creating a variable called stop that is like so:
stop = input("stop?")
But it's still not working.
import time
def Watch():
a = 0
hours = 0
while a < 1:
for minutes in range(0, 60):
for seconds in range(0, 60):
time.sleep(1)
print(hours,":", minutes,":", seconds)
hours = hours + 1
def whiles():
if start == "":
Watch()
if start == "":
return Watch()
def whiltr():
while Watch == True:
stop = input("Stop?")
#Ask the user to start/stop stopwatch
print ("To calculate your speed, we must first find out the time that you have taken to drive from sensor a to sensor b, consequetively for six drivers.")
start = input("Start?")
start = input("Stop")
whiles()
Perhaps all you need is something simple like:
import time
input('Start')
start = time.time()
input('Stop')
end = time.time()
print('{} seconds elapsed'.format(end-start))
Should probably use the time function instead of
def Watch():

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()

Problems using timer2 on Raspberry Pi

I'm having trouble using timer2 on the Raspberry Pi
Here's the code
**************************************************************
# tmr2_tst_04.py
# https://github.com/ask/timer2
# http://pymotw.com/2/threading/index.html#thread-objects
# ISSUES:
#
# *) Seems to respond only to even seconds
#
# *) Is off by 1 second. i.e. 4000 gives a 5 second interrupt
import timer2
import time # for sleep
import signal,sys
def signal_handler(signal, frame):
print 'You pressed Ctrl+C!'
timer.stop()
sys.exit(0)
#time_to_wait = 4500
#time_to_wait = 4999
time_to_wait = 4000.0 # gives 5-second cycle time !!!
#time_to_wait = 500.0 # doesn't work
tm = 0
tdiff = 0
tm_old = -1
iter = 0
to_print = False
def hello():
global iter
global tm, tdiff
global tm_old
global to_print
tm = time.time()
tdiff = (tm - tm_old) if tm_old > 0 else 0
tm_old = tm
iter += 1
# buf = "%3d %d %f %6.4f %s" % (iter, time_to_wait, tm, tdiff, "Hello world")
# print buf
to_print = True
# Set up to catch ^C
signal.signal(signal.SIGINT, signal_handler)
print 'Press Ctrl+C to exit'
# Set up timer interrupt routine
timer = timer2.Timer()
timer.apply_interval(time_to_wait, hello)
# Main program loop
while iter <= 10000:
if to_print:
buf = "%3d %d %f %6.4f %s" % (iter, time_to_wait, tm, tdiff, "Hello world")
print buf
to_print = False
time.sleep((time_to_wait/1000)/2)
timer.stop()
*************************************************************************
This runs the thread "hello" every 5000 msec on the Raspberry Pi, but every 4000 msec on an UBUNTU machine
Second issue - if I try for a short time interval, say
time_to_wait = 500
it doesn't work at all - just zips through the code with time differences of .1 msec!
It's calling Python's sleep function, which takes an arguments in seconds. Ideally, what you have done would convert that to .25 seconds, but all of the numbers involved are integers.
As integers, 500/1000 = 0, 0/2 = 0, and so on. So, it waits the requested 0 seconds before proceeding. Change 1000 to 1000.0, for example, and it should work.

Categories