I have a command in a line (Fit.perform() from import xspec, but never mind because the question is general and can be applicated also for other python commands) that takes a while to finish.
I simple want to know the time of execution while the command is running, so when it has not finished its execution yet.
This is necessary if I want to stop the command during its execution, for example because it is taking too much time to end.
So, I need something like this:
if **you_are_taking_so_much_time**:
do_something_else
It is not possible to use methods like time or timeit because they calculate the time only at the end of execution of a command and not while it is running.
Is it possible?
I'm using python 2.7 on MacOS.
You will have to use a monitor thread:
import threading
import time
done = False
def longfun():
global done
print("This will take some time.")
time.sleep(60)
done = True
def monitor():
global done
timeout = 10
print("Wait until timeout.")
while not done and timeout > 0:
time.sleep(1)
timeout -= 1
lt = threading.Thread(target=longfun)
lt.start()
mt = threading.Thread(target=monitor)
mt.start()
mt.join()
if done == False:
print("Long thread not done yet. Do something else.")
lt.join()
Note that this does wait until the 'long' thread is finished. You do not mention you want to stop the long running operation. If you do, you will have to correctly implement it in a thread, including start/stop/progress functionality (usually this works with a while loop that uses a running bit to see if it should continue.
like this:
import time,thread
def test_me(hargs):
func,args,timeout = hargs
start_time = time.time()
thread.start_newthread(func,args)
while True :
if My_expected_value:#where store this ?
print "well done !"
break
elif time.time() > (timeout + start_time) :
print "oh! to late, sorry !"
break
time.sleep(timeout/100)
thread.start_newthread(test_me,((func,args,timeout),))
important warnings : need use thread for Non-freezing application, got 3 thread for this: 1-main app, 2-test_me, 3- Your function(func)
Don't forget adding external variable to your function (for killing your function thread)
Related
I am trying to run a specific function in my python file. However, when I run the method with the timer that calls said function, it executes everything that it's supposed to, but then exits the job after the first time. I need it to continue to run the function after the specified time.
This is the function that contains the timer:
def executor(file):
x = datetime.today()
y = x.replace(day=x.day, hour=x.hour, minute=x.minute, second=x.second+10, microsecond=0)
delta_t = y-x
secs = delta_t.seconds+1
t = Timer(secs, parse_file, [file])
t.start()
The function that I am trying to call, is parse_file(file_name).
I am passing in the file_name when calling the executor function.
You haven't given enough detail of what your actual issue is, what code do you want to run more than once? Can you show the code that actually calls this function?
When you call start, the main thread will continue executing from that spot, while the task you scheduled will call the parse_file method at the specified time, and exit once complete. It sounds to me like you don't have anything that is keeping your main thread alive (that is, you don't have any more code after you call the executor).
Here is a small example showing how you can use the Timer to execute tasks while the main thread is still working. You can keep typing in input, and the print statement will show you all the threads that completed since the last time you typed an input.
from threading import Timer
import sys
def scheduled_task(arg):
print("\ntask complete arg %s!\n"%(arg))
def run_scheduled_task(arg):
timer = Timer(10, scheduled_task, [arg])
timer.start()
done = False
while not done:
user_input = input("Give me some input (exit to stop): ")
if user_input == 'exit':
print('Exiting')
done = True
else:
run_scheduled_task(user_input)
Forgive me, I am a newbie. I've surveyed some solution. But it is so hard for me to understand and to modify that. (Or maybe there is no solution in line with my imagination?). And I hope it can work on Ubuntu & Win7.
There is an example like this.
import random,time
def example():
while random.randint(0,10) != 1:
time.sleep(1)
print "down"
example()
And my imagination is...
If, the example() run over 10s, then rerun the example() again. (And maybe there is a place I can code anything else. Like I want to record the timeout event on TXT, and I can code the code at that place.)
Else, do nothing.
Is it possible to do that?
You can run a watch-dog in a separate thread that interrupts the main thread (that runs example) when it exceeds the time limit. Here is a possible implementation, with timeout lowered to 3s for ease of debugging:
import time, threading, thread
def watchdog_timer(state):
time.sleep(3)
if not state['completed']:
thread.interrupt_main()
def run_example():
while True:
state = {'completed': False}
watchdog = threading.Thread(target=watchdog_timer, args=(state,))
watchdog.daemon = True
watchdog.start()
try:
example()
state['completed'] = True
except KeyboardInterrupt:
# this would be the place to log the timeout event
pass
else:
break
I'm not sure if I fully understood what you want to achieve, but as you're constantly looping and only have one short and predictable blocking command, you could simply store the time when the loop started and then compare it to the current time once per loop iteration. If the difference exceeds your limit, do whatever you want:
import random,time
time_limit=10
def example():
time_start = time.time() # store current time (seconds since 1970)
while random.randint(0,10) != 1:
time.sleep(1)
if (time.time() >= time_start + time_limit): # compare with current time
print "canceled!"
break # break the while-loop
print "down"
example()
import time
number = 1
while number > 0:
print "Testing"
time.sleep(5) #print every 5 seconds
That is just an example loop. I'm a semi-beginner and I'm not sure how to make a keypress(any key is fine) display how long the program has been running. This program will be running on Windows 7 and Linux.
Thank you very much.
Welcome to Stack Overflow and to Python! You'll like it here.
First, I'll show you how to print out the time your code has been running. The time module includes a time() function that gets the current time as a Unix timestamp (the number of seconds since January 1, 1970). If you assign it to a variable at the start of the function, you can simply call it each time through the loop and subtract it from the current time to get your runtime. With me so far?
(You can also remove your number variable and the number > 0 check and simply replace it with True.)
import time
start_time = time.time()
while True:
print "I've been running for %d seconds!" % (time.time() - start_time)
time.sleep(5) #print every 5 seconds
But you asked how to get it each time the user presses a key. If you just want 'enter', you can do:
import time
start_time = time.time()
while True:
print "I've been running for %d seconds!" % (time.time() - start_time)
raw_input("Press Enter...")
The raw_input() function will wait for the user to press Enter, then print out the runtime.
One problem at a time.
How do you find how long your program has been running at the point at which you want to calculate?
How do you detect a key-press?
How do you get the program to produce 1) when 2) happens?
Try each problem in turn, then ask if you need help.
There are a lot of complexities and approaches for a such a simple question.
If you are looking for up time of a currently running process, use the OS to query that process with the subprocess module to run a command line operation such as 'ps | grep "foo" '
Usually programs do only one thing at a time. For example, the code could either do work OR look for a keypress. If you need to run have to run two different sections of code concurrently, spawn (run) the code segments as separate threads . For your question you could spawn two threads (pieces of code), one to do work and one to query up time.
Use the threading module in python to wrap the worker function and create a query thread. However, when the worker thread is done, you will want the query thread to terminate also. One way to do this is to define it as a daemon thread. Daemon threads terminate when they are the only threads alive.
For example:
from time import sleep
import datetime
import threading
def do_someting():
MAX_RUN_TIME = 300 #Seconds
for i in xrange(MAX_RUN_TIME):
print i,
sleep (1)
class worker_thread(threading.Thread):
def run(self):
do_someting()
class keypress_daemon_thread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self) # Initialize the parent class
self.daemon = True # Terminates if only daemon threads are left
def run(self):
startTime = datetime.datetime.now()
while True:
raw_input()
timeDelta = datetime.datetime.now() - startTime
print 'Up for', timeDelta
if __name__ == '__main__':
workerThread = worker_thread()
keyPressThread = keypress_daemon_thread()
workerThread.start()
keyPressThread.start()
workerThread.join()
I have a "do..., until..." structure in Python as follows:
while True:
if foo() == bar():
break
It works fine (jumps out in the end) in most of the cases. However, in some of the cases where the condition is never met, it will get stuck there.
Figuring out what are these cases is kind of difficult, since it is essentially a random process behind. So I wish to set a "timeout" thing for the while loop.
Say, if the loop has been running for 1s, but still not yet stops, I wish the loop to terminate itself.
How may I do this?
Update: Here is the actual code:
while True:
possibleJunctions = junctionReachability[junctions.index(currentJunction)]
nextJunction = random.choice(filter(lambda (jx, jy): (jx - currentJunction[0]) * (endJunction[0] - currentJunction[0]) > 0 or (jy - currentJunction[1]) * (endJunction[1] - currentJunction[1]) > 0, possibleJunctions) or possibleJunctions)
if previousJunction != nextJunction: # never go back
junctionSequence.append(nextJunction)
previousJunction = currentJunction
currentJunction = nextJunction
if currentJunction == endJunction:
break
import time
loop_start = time.time()
while time.time() - loop_start <= 1:
if foo() == bar():
break
EDIT
Dan Doe's solution is simplest and best if your code is synchronous (just runs in a single thread) and you know that the foo and bar functions always terminate within some period of time.
If you have asynchronous code (like a GUI), or if the foo and bar functions you use to test for termination conditions can themselves take too long to complete, then read on.
Run the loop inside a separate thread/process. Run a timer in another process. Once the timer expires, set a flag that would cause the loop to terminate.
Something like this (warning: untested code):
import multiprocessing
import time
SECONDS = 10
event = multiprocessing.Event()
def worker():
"""Does stuff until work is complete, or until signaled to terminate by timer."""
while not event.is_set():
if foo() == bar():
break
def timer():
"""Signals the worker to terminate immediately."""
time.sleep(SECONDS)
event.set()
def main():
"""Kicks off subprocesses and waits for both of them to terminate."""
worker_process = multiprocessing.Process(target=worker)
timer_process = multiprocessing.Process(target=timer)
timer_process.start()
worker_process.start()
timer_process.join()
worker_process.join()
if __name__ == "__main__":
main()
If you were worried about the foo and bar functions taking too long to complete, you could explicitly terminate the worker process from within the timer process.
I recommend using a counter. This is a common trick to detect non-convergence.
maxiter = 10000
while True:
if stopCondition(): break
maxiter = maxiter - 1
if maxiter <= 0:
print >>sys.stderr, "Did not converge."
break
this requires the least overhead and usually adapts best to different CPUs: even on a faster CPU, you want the same termination behavior; instead of a time-based timeout.
However, it would be even better if you would detect being stuck e.g. with some criterion function that no longer improves.
I have two functions, draw_ascii_spinner and findCluster(companyid).
I would like to:
Run findCluster(companyid) in the backround and while its processing....
Run draw_ascii_spinner until findCluster(companyid) finishes
How do I begin to try to solve for this (Python 2.7)?
Use threads:
import threading, time
def wrapper(func, args, res):
res.append(func(*args))
res = []
t = threading.Thread(target=wrapper, args=(findcluster, (companyid,), res))
t.start()
while t.is_alive():
# print next iteration of ASCII spinner
t.join(0.2)
print res[0]
You can use multiprocessing. Or, if findCluster(companyid) has sensible stopping points, you can turn it into a generator along with draw_ascii_spinner, to do something like this:
for tick in findCluster(companyid):
ascii_spinner.next()
Generally, you will use Threads. Here is a simplistic approach which assumes, that there are only two threads: 1) the main thread executing a task, 2) the spinner thread:
#!/usr/bin/env python
import time
import thread
def spinner():
while True:
print '.'
time.sleep(1)
def task():
time.sleep(5)
if __name__ == '__main__':
thread.start_new_thread(spinner, ())
# as soon as task finishes (and so the program)
# spinner will be gone as well
task()
This can be done with threads. FindCluster runs in a separate thread and when done, it can simply signal another thread that is polling for a reply.
You'll want to do some research on threading, the general form is going to be this
Create a new thread for findCluster and create some way for the program to know the method is running - simplest in Python is just a global boolean
Run draw_ascii_spinner in a while loop conditioned on whether it is still running, you'll probably want to have this thread sleep for a short period of time between iterations
Here's a short tutorial in Python - http://linuxgazette.net/107/pai.html
Run findCluster() in a thread (the Threading module makes this very easy), and then draw_ascii_spinner until some condition is met.
Instead of using sleep() to set the pace of the spinner, you can wait on the thread's wait() with a timeout.
It is possible to have a working example? I am new in Python. I have 6 tasks to run in one python program. These 6 tasks should work in coordinations, meaning that one should start when another finishes. I saw the answers , but I couldn't adopted the codes you shared to my program.
I used "time.sleep" but I know that it is not good because I cannot know how much time it takes each time.
# Sending commands
for i in range(0,len(cmdList)): # port Sending commands
cmd = cmdList[i]
cmdFull = convert(cmd)
port.write(cmd.encode('ascii'))
# s = port.read(10)
print(cmd)
# Terminate the command + close serial port
port.write(cmdFull.encode('ascii'))
print('Termination')
port.close()
# time.sleep(1*60)