I'm making a simple client/server program in Python 3 and in the client I would like a clock or printout of the running time. I'm trying to make it in a loop that starts at the beginning of the program, but in a thread so the rest of the code keeps going.
class time_thread():
def run(self):
loop = 0
while (zetime > -1):
print(zetime);
zetime = zetime + 1;
time_thread.start()
zetime = 0
This is what I have so far, but it doesn't work. It says:
time_thread has no attribute start()
I'm new to this and haven't used threads before, so I'm not sure how to go about this. Is there a better way?
I think this is what you're looking for:
import time, sys
zetime = 0
while (zetime > -1):
sys.stdout.write("\r" + str(zetime))
sys.stdout.flush()
time.sleep(1)
zetime = zetime + 1;
First of all , to use Thread module, you have to inherit the class Thread on your class, so you can use their methods like start.
To calculate time, you can use datetime.
from datetime import datetime
from time import sleep
start_time = datetime.now()
sleep(5) # code that you want to calculate.
end_time = datetime.now()
print(end_time - start_time)
Just place this
So let's say you define a function elapsed_time such as:
import time, sys
def elapsed_time(time_start):
''' time_start: a time.time()
Goal: print the elapsed time since time_start '''
# Allow to stop the counting once bool_time = False in the main program
global bool_elapsed_time
# loop while the condition
while bool_elapsed_time == True:
# Note: erase and write below does not work in spyder but in a shell yes
print ("Elapsed time: {} seconds".format(int(time.time() - time_start))),
sys.stdout.flush()
print ("\r"),
time.sleep(1)
# erase the line with elapsed time to clean the shell at the end
sys.stdout.flush()
print ("\r"),
Then in your program:
import threading
bool_elapsed_time = True
t = threading.Thread(name='child procs', target=elapsed_time, args=(time.time(),))
t.start()
## Here add the job you want to do as an example:
time.sleep(10)
bool_elapsed_time = False #to stop the elapsed time printing
Should do the job you want to do.
Note: I used python 2.7 so it might be slightly different with 3.x
Related
I'm trying to run a function in python for a specific amount of time (say 100 sec), and then move on to run another function for a specific amount of time.
I've tried creating a counter and using while counter < (some frame number). I've also tried using datetime by doing something like
end_time = datetime.now() + timedelta(seconds=100)
while datetime.now() < end_time:
These things don't seem to be working and I don't know why.
Here is my current version of the code:
class FicTracAout90deg(object):
def run(self, gain_yaw = 1):
end_time = datetime.now() + timedelta(seconds=10)
while datetime.now() < end_time:
for item in self.pubsub.listen():
message = item['data']
try:
data = json.loads(message)
except TypeError:
continue
if data['type'] == 'reset':
self.time_start = time.time()
self.heading_rate_calc.reset(self.time_start)
else:
time_curr = time.time()
heading = data['heading']
intx = data['intx']
inty = data['inty']
velx = data['velx']
vely = data['vely']
velheading = data['deltaheading']
self.accum_heading += velheading
self.accum_x += velx
self.accum_y += vely
time_elapsed = time_curr - self.time_start
I'm running this with the following code:
from analogoutNoise import FicTracAoutNoise
from analogout90deg import FicTracAout90deg
import time
#for a certain amount of time run block 1
#Block 1
for x in range(2):
client = FicTracAout90deg()
client.run(1)
The 'run' function never seems to stop, and I don't understand why.
Likely the issue is that the line for item in self.pubsub.listen(): never returns a value and so it doesn't finish executing. If this statement doesn't finish execution then the rest of the code is not run and the outer loop is not checked.
Please post a SSCCE. In order to get your script to run, I had to add from datetime import datetime, timedelta. The following code does work, and is similar structurally to yours:
from datetime import datetime, timedelta
from time import sleep
tBegin = datetime.now()
tEnd = tBegin + timedelta(seconds=100)
while datetime.now() < tEnd:
print(datetime.now())
sleep(10)
print(datetime.now())
Since this works, it seems to me that the problem is not with the time endpoints, but rather with the internals of your while loop. It can perform a very large number of iterations in 100 sec., which means it's pinning the processor for all that time and accumulating a lot of garbage. It's probably better to think up a different approach, as #iamchoosinganame suggested.
What i'm trying to do is print or execute a certain string after
certain amount of time, in case of this function it is 20 seconds,
the problem is on the second loop, sure it waits 20 seconds on first loop,
but the second loop it no longer wait, it just keeps printing..
why does this happen? and how can i solve it?
from threading import Timer
import time
startlog = time.time()
def tess():
tm = 0
while True:
tm += 1
print(tm)
tess()
time.sleep(1)
You need to reset startlog between calls to tess that "succeed" (have passed 20 s), this code works the way you want (but is ugly because of the global variables).
import time
startlog = time.time()
def tess():
global startlog
if time.time() - 20 > startlog:
print('its been 20 secs')
startlog = time.time()
tm = 0
while True:
tm += 1
print(tm)
tess()
time.sleep(1)
You need to update your startlog variable inside loop in tess() function. You need to replace
start = time.time()
with:
startlog = time.time()
You have to change start = time.time() to startlog = time.time() and define such variable as global or nonlocal:
def tess():
nonlocal startlog
...
startlog = time.time()
Or just wait 20 secs: time.sleep(20)
It sounds like you are trying to run something for 20 seconds in the background, and then execute your function.
If this is the case, you threading / multiprocessing makes more sense.
Using this decorator, your code could be rewritten as
#time_limit(20)
def will_stop_after_20_secs():
print ("doing stuff")
time.sleep(20)
will_stop_after_20_secs()
print ("20 seconds had passed")
I am trying to figure out how to do the following:
If "some logic" occurs for more than 15 seconds:
"execute some code"
Im not quite sure how to ask python to do this. I am working with stock prices and my index column is dtype='datetime64[ns].
I tried searching other threads for hints on how to do this but i wasn't even quite sure what to search for.
Sorry in advance if its a very elementary question.
try takinng the current time and comparing it every tick
One way to accomplish this is to use threads (multiprocessing) as they would be 2 tasks "some logic" and the "scheduler".
This can be addressed easily with the following logic:
import threading
import time
lock = threading.Lock()
cond = threading.Condition(threading.Lock())
def waitLock(timeout):
with cond:
current_time = start_time = time.time()
while current_time < start_time + timeout:
if lock.acquire(False):
return True
else:
cond.wait(timeout - current_time + start_time)
current_time = time.time()
return False
Source: How to implement a Lock with a timeout in Python 2.7
import time
def check():
if not some_logic(): return False
start_time = time.time()
while time.time() - start_time <= 15:
if not some_logic(): return False
return True
if check():
... # do stuff
This runs some_logic as many times as possible to ensure that it returns True throughout the whole 15-second period.
I have a code:
function_1()
function_2()
Normally, function_1() takes 10 hours to end.
But I want function_1() to run for 2 hours, and after 2 hours, function_1 must return and program must continue with function_2(). It shouldn't wait for function_1() to be completed. Is there a way to do this in python?
What makes functions in Python able to interrupt their execution and resuming is the use of the "yield" statement -- your function then will work as a generator object. You call the "next" method on this object to have it start or continue after the last yield
import time
def function_1():
start_time = time.time()
while True:
# do long stuff
running_time = time.time() -start_time
if running_time > 2 * 60 * 60: # 2 hours
yield #<partial results can be yield here, if you want>
start_time = time.time()
runner = function_1()
while True:
try:
runner.next()
except StopIteration:
# function_1 had got to the end
break
# do other stuff
If you don't mind leaving function_1 running:
from threading import Thread
import time
Thread(target=function_1).start()
time.sleep(60*60*2)
Thread(target=function_2).start()
You can try to use module Gevent: start function in thread and kill that thread after some time.
Here is example:
import gevent
# function which you can't modify
def func1(some_arg)
# do something
pass
def func2()
# do something
pass
if __name__ == '__main__':
g = gevent.Greenlet(func1, 'Some Argument in func1')
g.start()
gevent.sleep(60*60*2)
g.kill()
# call the rest of functions
func2()
from multiprocessing import Process
p1 = Process(target=function_1)
p1.start()
p1.join(60*60*2)
if p1.is_alive():p1.terminate()
function_2()
I hope this helps
I just tested this using the following code
import time
from multiprocessing import Process
def f1():
print 0
time.sleep(10000)
print 1
def f2():
print 2
p1 = Process(target=f1)
p1.start()
p1.join(6)
if p1.is_alive():p1.terminate()
f2()
Output is as expected:
0
2
You can time the execution using the datetime module. Probably your optimizer function has a loop somewhere. Inside the loop you can test how much time has passed since you started the function.
def function_1():
t_end = datetime.time.now() + datetime.timedelta(hours=2)
while not converged:
# do your thing
if datetime.time.now() > t_end:
return
I want to have an app where if I click a button I add X amount of time to my running countdown timer.
I'm guessing I have to use threads for this but am not sure how to implement it..
Here is the code I have so far:
def countdown_controller(add_time):
end_it = False
def timer(time_this):
start = time.time()
lastprinted = 0
finish = start + time_this
while time.time() < finish:
now = int(time.time())
if now != lastprinted:
time_left = int(finish - now)
print time_left
lastprinted = now
if end_it == True:
now = finish
time.sleep(0.1)
# Check if the counter is running otherwise just add time.
try:
time_left
except NameError:
timer(add_time)
else:
if time_left == 0:
timer(add_time)
else:
add_this = time_left
end_it = True
while now != finish:
time.sleep(0.1)
timer(add_time + add_this)
Obviously this will not work, because every time I call countdown_controller(15) fx, it will start counting down for 15 seconds and if I click my button nothing happens until the timer is ended.
Help would be greatly appreciated.
I would say that there is a flaw in the design of the code, because your screen output blocks down the entire program doing nothing (time.sleep(0.1)).
Typically what you want to to do in these cases is having a main loop in your program that cycles through the various operations that make your program run. This guarantees a sensible distribution of system resources between the various tasks.
In your specific case, what you would like to have in your main loop is:
Check user input (has extra time been added?)
Update output of the countdown
Example implementation:
import time
import curses
# The timer class
class Timer():
def __init__(self):
self.target = time.time() + 5
def add_five(self):
self.target += 5
def get_left(self):
return int(self.target-time.time())
# The main program
t = Timer()
stdscr = curses.initscr()
stdscr.nodelay(True)
curses.noecho()
# This is the main loop done in curses, but you can implement it with
# a GUI toolkit or any other method you wish.
while True:
left = t.get_left()
if left <= 0:
break
stdscr.addstr(0, 0, 'Seconds left: %s ' % str(left).zfill(3))
c = stdscr.getch()
if c == ord('x') :
t.add_five()
# Final operations start here
stdscr.keypad(0)
curses.echo()
curses.endwin()
print '\nTime is up!\n'
The above program will increase the counter of 5 seconds if you press the x key (lowercase). Most of the code is boilerplate to use the curses module, but of course if you use PyGTK, PySide or any other graphical toolkit, it will be different.
EDIT: As a rule of thumb, in python you want to avoid threading as much as you can, both because it often (but not always) slows down programs (see "Global Interpreter Lock") and because it makes software harder to debug/maintain.
HTH!
I would probably have a Timer object with a finish attribute that I could simply add an int to. Have that timer running in another thread that you can then query for the current time remaining from your GUI.
class Timer(object):
def __init__(self, length):
self.finish = time.time() + length
def get_time(self):
return time.time() >= self.finish