Timing how long it takes for subprocess to complete - python

I currently have a method that executes other python scripts by using subprocess calls, I was wondering if there was anyway I could time how long it takes for this to complete? The scripts are running in an interval, what I want to achieve from this is to check whether the scripts finish within that interval.
def execute_scripts(script_name):
process = sp.Popen(['python2.7', script_name])
print 'executing - ' + script_name

Use timeit to time the execution of small bits of code.
#sleep2.py
import time
time.sleep(2)
You need to use subprocess.call to block until the call is finished.
import timeit
import subprocess as sp
def execute_scripts(script_name):
process = sp.call(['python2.7', script_name])
print 'executing - ' + script_name
t = timeit.Timer("execute_scripts('sleep2.py')", setup="from __main__ import execute_scripts")
print 'time taken : %f seconds' % t.timeit(1)
executing - sleep2.py
time taken : 2.032273 seconds
Alternatively, you can generalise this by writing a decorator to time any function call
import time
import subprocess as sp
def timed_execution(function):
def wrapper(arg):
t1 = time.time()
function(arg)
t2 = time.time()
return 'time taken : %f seconds' % (t2 - t1) + "\n"
return wrapper
#timed_execution
def execute_scripts(script_name):
sp.call(['python2.7', script_name])
print 'executing - ' + script_name
print execute_scripts('sleep2.py')
executing - sleep2.py
time taken : 2.025291 seconds

Do you need the program to keep running while the scripts are executing? If not, you can block your program execution until the process finishes and report the time it took:
def execute_scripts(script_name):
time_start = time.time()
print "starting process"
process = sp.call(['python2.7', script_name])
print 'finished process %s in %s s" % (process, time.time() - start_time)

Related

Is there a solution that allows you to perform a task every specified number of seconds in a thread without putting it to sleep?

like in questien Is there a solution that allows you to perform a task every specified number of seconds in a thread without putting it to sleep in python?
The following code runs thread1 one time after every 30 seconds:
import threading
def thread1:
pass
L1.acquire()
if "__name__" == "__main__":
specific_time = 30
t1 = threading.Thread(target=thread1)
L1 = threading.Lock(blocking=True)
t1.start()
init_time = time.time()
while 1:
if (time.time() - init_time) >= specific_time:
L1.release()
init_time = time.time()
1st way
You can do it useing threading.Timer
from threading import Timer
def hello():
print "hello, world"
t = Timer(30.0, hello)
t.start() # after 30 seconds, "hello, world" will be printed
2nd way
Just check if the specific time passed. Then run your_function() in a thread
import time
current_milli_time = lambda: int(round(time.time() * 1000))
def your_function():
last_run_millis = current_milli_time()
while 1:
now_millis = current_milli_time()
delta_time = now_millis - last_run_millis
if delta_time > 3000:
last_run_millis = now_millis
print("Do your stuff here")
your_function()

Python :Lambda Function Details in Decorator

Trying to add executing Process(Test,a,b) Name in the decoration where i am calculating Elapsed Time.Need Suggestions.
Final Expected Logs:
Process **a** elapsed time :3.8 || Rowcount=1833
Process **test** elapsed time :7.8 || Rowcount=1133
code
import time
from queries import a,b,test
def elapsedTimeTracker_decorator(func):
def wrapper():
start_time = time.time()
func()
print(test)
end_time = time.time()
elapsed_time = end_time - start_time
print('elapsed_time:'+ str(elapsed_time) +'||' + 'RowCount:' + str(cursor.rowcount))
return wrapper
print "Process a started"
elapsedTimeTracker_decorator(lambda: cursor.execute(a))()
print "Process Test started"
elapsedTimeTracker_decorator(lambda: cursor.execute(Test))()
print "Process b started"
elapsedTimeTracker_decorator(lambda: cursor.execute(b))()
a,b & test Consists of SQL Update Queries
test = """INSERT INTO users
select * from user_all where user_id=54549172 """
If you wish to print extra data for a decorated lambda that takes no arguments, then you have to pass it to your decorator:
def elapsedTimeTracker_decorator(func, test):
def wrapper():
start_time = time.time()
func()
print(f'Process {test} elapsed time: {time.time() - start_time} || Rowcount={cursor.rowcount}')
return wrapper
elapsedTimeTracker_decorator(lambda: cursor.execute(test), test)()
Other than that I have no idea where your test is supposed to comes from. Please elaborate with more details if that is not a suitable solution.
EDIT: Based on the latest information provided, it is clear that you do not need to use a lambda, nor a decorator with an inner wrapper. You could simply use a simple function that call the given one with the provided arguments and keywords that would take care of the call along with printing the execution time. For example:
from time import time as now
def time_call(func, *args, **kwargs):
cur = now()
func(*args, **kwargs)
print(
f'Executing {func.__qualname__}({repr(args)[1:-1]}, ' +
f'{"".join(f"{k}={v}" for k, v in kwargs.items())}) took ' +
f'{now() - cur} seconds.'
)
def test(foo, bar, baz):
pass
time_call(test, 'foo', 'bar', baz=None)
Which would prints something like:
Executing test('foo', 'bar', baz=None) took 0.0 seconds.

How do I see the time it took to run my program in Visual Studio Code?

Is there a way to see how long a script took to execute/complete in VS Code?
I'm looking for a message like:
Program finished in 30ms
Use 'time'
When your script starts:
import time
start_time = time.time()
do something # here your actual code/routine
print("Process finished --- %s seconds ---" % (time.time() - start_time))
You can create a simple decorator function to time your functions.
import time
def decoratortimer(decimal):
def decoratorfunction(f):
def wrap(*args, **kwargs):
time1 = time.monotonic()
result = f(*args, **kwargs)
time2 = time.monotonic()
print('{:s} function took {:.{}f} ms'.format(f.__name__, ((time2-time1)*1000.0), decimal ))
return result
return wrap
return decoratorfunction
#decoratortimer(2)
def callablefunction(name):
print(name)
print(callablefunction('John'))
I suggest using time.monotonic(which is a clock that doesnt go backwards) to increase the accuracy.
Easiest way to achieve this is by purely coding the time to program. perf_counter offers highest accuracy from the time functions.
from time import perf_counter, sleep
def main():
sleep(5)
start_time = perf_counter()
main() # Function to measure
passed_time = perf_counter() - start_time
print(f"It took {passed_time}") # It took 5.007398507999824
For finding your function run time prefer time.perf_counter() over time.time().
See the below link for details
Understanding time.perf_counter() and time.process_time()
You can create your own custom timer using something like this
from time import perf_counter
def f(a1,a2):
return a1 * a2
def timer(f,*args):
start = perf_counter()
f(*args)
return (1000 * (perf_counter()-start)) # this returns time in ms
a1 = np.random.rand(100)
a2 = np.random.rand(100)
np.mean([timer(f,a1,a2) for _ in range(100)]) # average out result for 100 runs
If you are using jupyter notebook use the following
%%timeit
f(a1,a2)

How to time how long my method takes to run?

I have a program that has multiple methods. I would like to measure how long it takes for each method to run when they are called.
For example
def func1:
blah
def func2:
blah
def main:
call func1 and func2 and measure their times
is there an easy way to do it.
I find the following piece of re-usable code handy when testing functions.
import timeit
def timed_function(f, *args, **kwargs):
myname = str(f).split(' ')[1]
def new_func(*args, **kwargs):
timer1 = timeit.default_timer()
result = f(*args, **kwargs)
timer2 = timeit.default_timer()
delta = timer2 - timer1
print('Function {} Time = {:6.3f}ms'.format(myname, delta*1000))
return result
return new_func
You can use it to decorate any function and then it will print the original function's name and execution time every time you run it.
Something like this:
#timed_function
def func1():
return sum([0.5 for i in range(10000)])
y = func1()
Code output:
Function func1 Time = 0.849ms
[I got the idea from here.]
Here's a code timing setup I wrote for myself, I use python 2.7
#!python2
import timeit
runs = 100
totalTime = 0.0; average = 0.0
testTimes = []
for i in range(runs):
startTimer = timeit.default_timer()
# >>>>> code to be tested goes here <<<<<
endTimer = timeit.default_timer()
timeInterval = endTimer - startTimer
testTimes.append(timeInterval)
totalTime += timeInterval
# running below statement causes each run longer to complete
# print '\n', '%1.4f' % timeInterval + ' seconds'
print
print ' Total time:', '%1.4f' % totalTime + ' seconds'
print 'Shortest time:', '%1.4f' % min(testTimes) + ' seconds'
print ' Longest time:', '%1.4f' % max(testTimes) + ' seconds'
print ' Average time:', '%1.4f' % (totalTime / runs) + ' seconds'
If you're running code from a separate file, perf_counter is the way to go. For example,
from time import perf_counter
def main():
start = perf_counter()
# Do stuff.
print(perf_counter() - start)
If you're testing code in the shell, there's an even easier way: the timeit module. It has two main functions: timeit and repeat. The former is simply a timer, the latter returns a list of times for different trials. https://docs.python.org/3/library/timeit.html?highlight=timeit#module-timeit
Just make sure to pass globals() as the globals argument if you're using imported functions!

executing specific statement at a given rate in python

I want to write a code which execute a statement specified number of times per second,
Many of you might be familier about the term rate
Here i want rate to be 30 per second
say i want to execute a function 30 times per second for 60 seconds
means rate=30/sec duration=60sec
Can any one tell me is their any api available in python to do the same ?
The sched module is intended for exactly this:
from __future__ import division
import sched
import time
scheduler = sched.scheduler(time.time, time.sleep)
def schedule_it(frequency, duration, callable, *args):
no_of_events = int( duration / frequency )
priority = 1 # not used, lets you assign execution order to events scheduled for the same time
for i in xrange( no_of_events ):
delay = i * frequency
scheduler.enter( delay, priority, callable, args)
def printer(x):
print x
# execute printer 30 times a second for 60 seconds
schedule_it(1/30, 60, printer, 'hello')
scheduler.run()
For a threaded environment, the use of sched.scheduler can be replaced by threading.Timer:
from __future__ import division
import time
import threading
def schedule_it(frequency, duration, callable, *args, **kwargs):
no_of_events = int( duration / frequency )
for i in xrange( no_of_events ):
delay = i * frequency
threading.Timer(delay, callable, args=args, kwargs=kwargs).start()
def printer(x):
print x
schedule_it(5, 10, printer, 'hello')
Try using threading.Timer:
def hello():
print "hello, world"
t = Timer(30.0, hello)
t.start() # after 30 seconds, "hello, world" will be printed
You can use time.time() to do what you want:
import time
def your_function():
# do something...
while True:
start = time.time() # gives current time in seconds since Jan 1, 1970 (in Unix)
your_function()
while True:
current_time = time.time()
if current_time - start >= 1.0/30.0:
break
This will make sure that the delay between calls of your_function is very close to 1/30 of a second, even if your_function takes some time to run.
There is another way: using Pythons built-in scheduling module, sched. I never used it, so I can't help you there, but have a look at it.
After some time spending i discovered how to do it well i used multiprocessing in python to achieve it
here's my solution
#!/usr/bin/env python
from multiprocessing import Process
import os
import time
import datetime
def sleeper(name, seconds):
time.sleep(seconds)
print "PNAME:- %s"%name
if __name__ == '__main__':
pros={}
processes=[]
i=0
time2=0
time1=datetime.datetime.now()
for sec in range(5):
flag=0
while flag!=1:
time2=datetime.datetime.now()
if (time2-time1).seconds==1:
time1=time2
flag=1
print "Executing Per second"
for no in range(5):
i+=1
pros[i] = Process(target=sleeper, args=("Thread-%d"%i, 1))
j=i-5
for no in range(5):
j+=1
pros[j].start()
j=i-5
for no in range(5):
j+=1
processes.append(pros[j])
for p in processes:
p.join()

Categories