I have a question about adding delay after calling various functions.
Let's say I've function like:
def my_func1():
print("Function 1")
def my_func2():
print("Function 2")
def my_func3():
print("Function 3")
Currently I've added delay between invoking them like below:
delay = 1
my_func1()
time.sleep(delay)
my_func2()
time.sleep(delay)
my_func3()
time.sleep(delay)
As you can see I needed a few times time.sleep, which I would like to avoid.
Using decorator is also not an option, since it might be that I would like to avoid delay when calling one of this function not in a group.
Do you have any tip how to beautify this?
You can define something like this:
def delay_it(delay, fn, *args, **kwargs):
return_value = fn(*args, **kwargs)
time.sleep(delay)
then
a = delay_it(1, my_func1, "arg1", arg2="arg2")
b = delay_it(1, my_func2, "arg3")
...
I've tested this based on "How to Make Decorators Optionally Turn On Or Off" (How to Make Decorators Optionally Turn On Or Off)
from time import sleep
def funcdelay(func):
def inner():
func()
print('inner')
sleep(1)
inner.nodelay = func
return inner
#funcdelay
def my_func1():
print("Function 1")
#funcdelay
def my_func2():
print("Function 2")
#funcdelay
def my_func3():
print("Function 3")
my_func1()
my_func2()
my_func3()
my_func1.nodelay()
my_func2.nodelay()
my_func3.nodelay()
Output:
Function 1
inner
Function 2
inner
Function 3
inner
Function 1
Function 2
Function 3
You can see that it can bypass the delay.
Not sure if I know what you mean but you could try:
functions = [my_func1, my_func2, my_func3]
for func in functions:
func()
time.sleep(1)
It's not a good way to handle delay in a function; because each function should do only one thing.
Dont't do this:
def my_func(delay):
# do stuff
if delay>0:
time.sleep(delay)
Try to make a delay handler function and put suitable delay after each function you pass to it.
Try this:
def delay_handler(functions_list,inputs_list,delay_list):
for function,cur_input,delay in zip(functions_list,inputs_list,delay_list):
function(*cur_input)
time.sleep(delay)
Tip 1: Zip will iterate throw each list (any iterable) simultaneously; first elements in inputs_list and delay_list are for first function in function_list and etc.
Tip 2: The '*' behind a list will unpack it.
Related
I am studying on decorators in Python. I was trying to use the decorators with arguments. I'm having a problem with the decorators. I defined two inner function in the default decorator function. It returns none when I use it as below:
def prefix(write: bool = False):
def thread(func):
def wrapper(*args, **kwargs):
t1 = Thread(target=func, args=args, kwargs=kwargs)
t1.start()
if write:
print("write parameter is true.")
return wrapper
return thread
#prefix(write=True)
def something(x):
return x + x
print(something(5))
As you see, I defined two different functions named prefix and something. If the write parameter is true, it prints the string. But something function is printing "None" instead of printing 5 + 5.
What's wrong?
Well, your wrapper() function doesn't have a return statement, so it will always return None.
Furthermore, how would you expect it to print 5 + 5 (or rather, the result thereof) when that may not have been computed yet, considering you're starting a new thread to do that and never do anything with the return value of func at all?
IOW, if we expand your example a bit:
import time
from threading import Thread
def prefix(write: bool = False):
def thread(func): # <- this function replaces `something`
def wrapper(*args, **kwargs):
t1 = Thread(target=func, args=args, kwargs=kwargs)
t1.start()
if write:
print("write parameter is true.")
return "hernekeitto"
return wrapper
return thread
#prefix(write=True)
def something(x):
print("Computing, computing...")
time.sleep(0.5)
print("Hmm, hmm, hmm...")
time.sleep(0.5)
print("Okay, got it!")
return x + x
value = something(9)
print("The value is:", value)
This will print out
Computing, computing...
write parameter is true.
The value is: hernekeitto
Hmm, hmm, hmm...
Okay, got it!
As you can see, the thread's first print() happens first, then the write print, then the value print, and then the rest of what happens in the thread. And as you can see, we only know what x + x is after "Okay, got it!", so there's no way you could have returned that out of wrapper() where "hernekeitto" is returned.
See futures (or the equivalent JavaScript concept promises) for a "value that's not yet ready":
import time
from concurrent.futures import Future
from threading import Thread
def in_future(func):
def wrapper(*args, **kwargs):
fut = Future()
def func_wrapper():
# Wraps the threaded function to resolve the future.
try:
fut.set_result(func(*args, **kwargs))
except Exception as e:
fut.set_exception(e)
t1 = Thread(target=func_wrapper)
t1.start()
return fut
return wrapper
#in_future
def something(x):
print("Computing, computing...")
time.sleep(0.5)
print("Hmm, hmm, hmm...")
time.sleep(0.5)
print("Okay, got it!")
return x + x
value_fut = something(9)
print("The value is:", value_fut)
print("Waiting for it to be done...")
print("Here it is!", value_fut.result())
This prints out
Computing, computing...
The value is: <Future at 0x... state=pending>
Waiting for it to be done...
Hmm, hmm, hmm...
Okay, got it!
Here it is! 18
so you can see the future is just a "box" where you'll need to wait for the actual value to be done (or an error to occur getting it).
Normally you'd use futures with the executors in concurrent, but the above is an example of how to do it by hand.
I have two functions, function1 and function2. I want to execute function1 for only 5 seconds, and then execute function2 for only 3 seconds and then repeat it.
I tried time.sleep() function, but it freezes entire program not executing any function.
I tried asyncio and threading, but it just executing both functions at same time.
def function1():
//do something
def funtion2():
//do something else
while True:
function1()
// execute function1 for 5 seconds
function2()
// execute function2 for 3 seconds
How precise do you need to be? Are you needing to account for the runtime of the functions themselves? That will be quite difficult.
Here's a simple approach:
import time # built-in module
def timed_execution(func, s, *args, **kwargs):
t0 = time.time()
while True:
func(*args, **kwargs)
if time.time() - t0 >= s:
break
timed_execution(function1, 5)
timed_execution(function2, 3)
If you'd like to get a little more fancy, and the times your functions need to execute is always the same, you could use a decorator:
import time
def timer(s):
def timed_func(func):
def timed_execution(*args, **kwargs):
t0 = time.time()
while True:
func(*args, **kwargs)
if time.time() - t0 >= s:
break
return timed_execution
return timed_func
#timer(5)
def function1():
pass
#timer(3)
def function2():
pass
If you want to use a decorator with a parameter for the amount of time, but only optionally, you'll need to do a bit more work. See how to do a conditional decorator.
I'm trying to understand the real world use of decorators.
coming on the decorators we all know that it is used to decorate the function.
It means we can add something extra to the existing function but it can be done by using other simple function also we can call one function which will call the other function. So why we need to use the decorators.
I have already tried to make two program
with decorators
def decor_result(result_as_argument):
def new_function(marks):
for i in marks:
if i>= 75:
print("Congrats distiction",i)
else:
result_as_argument(marks)
return new_function
#decor_result
def result(marks):
for i in marks:
if i >= 35:
pass
else:
print("Fail")
break
else:
print("Pass")
result([79,65,55,78,12])
without decorators
def result_distict(marks):
for i in marks:
if i>= 75:
print("Congrats distiction",i)
else:
result(marks)
def result(marks):
for i in marks:
if i >= 35:
pass
else:
print("Fail")
break
else:
print("Pass")
result_distict([79,65,55,78,12])
result([79,65,55,78,12])
By doing this I came to know that without using decorators, it is more simplified and we are free to use any of the function what we want and by using decorators we can not use the old function so why and where to use decorators?
In your example, doing a decorator is not necessary. You want to use a decorator when you're trying to implement a specific behavior to a set of functions. For instance, let's say you're trying to display the execution time of all the functions in your script.
Solution 1) You add a little piece of code everywhere to display it:
from time import time
def f1():
t0 = time()
# f1 body
print("Execution time of f1: {}".format(time()-t0))
def f2():
t0 = time()
# f2 body
print("Execution time of f2: {}".format(time()-t0))
As you can see, the code is very repetitive. If you want to change anything in this shared behavior, then you have to modify all the functions. That's where decorator are useful.
2) Using decorators:
def timer(func):
def wrapper(*args,**kwargs):
t0 = time()
res = func(*args,**kwargs)
duration = time()-t0
print("Execution time of {}: {} s".format(func.__name__, duration))
return res
return wrapper
#timer
def f1():
# body of f1
#timer
def f2():
# body of f2
I'm trying to implement threading(with using decorators) to my application, but can't understand some things about locks and managing threads.
import threading
def run_in_thread(fn):
def run(*k, **kw):
t = threading.Thread(target=fn, args=k, kwargs=kw)
t.start()
return run
class A:
#run_in_thread
def method1(self):
for x in range(10000):
print x
#run_in_thread
def method2(self):
for y in list('wlkefjwfejwiefwhfwfkjshkjadgfjhkewgfjwjefjwe'):
print y
def stop_thread(self):
pass
c = A()
c.method1()
c.method2()
As I understand, method1 and method2 are not synchronized, but synchronizing of that stuff implementing with help of locks. How I can add locks to my decorator-function?
How can I realize method for stopping long threads using decorators?
If you extend the function to
def run_in_thread(fn):
def run(*k, **kw):
t = threading.Thread(target=fn, args=k, kwargs=kw)
t.start()
return t # <-- this is new!
return run
i. e., let the wrapper function return the created thread, you can do
c = A()
t1 = c.method1()
t1.join() # wait for it to finish
t2 = c.method2()
# ...
i. e, get the thread where the original method runs in, do whatever you want with it (e. g. join it) and only then call the next method.
If you don't need it in a given case, you are free to omit it.
If you want to synchronize the two threads you simply need to add locks inside the decorated functions, not the decorators themselves.
There is not a simple way to directly stop a Thread, only way is to use an Event to signal the thread it must exit.
For threading decorators you can take a look at pebble.
Maybe Semaphores could help in decorators, something like this - calculating factorial numbers from 1 to 1000:
import threading
from functools import wraps
from math import factorial
DIC = {}
def limit(number):
''' This decorator limits the number of simultaneous Threads
'''
sem = threading.Semaphore(number)
def wrapper(func):
#wraps(func)
def wrapped(*args):
with sem:
return func(*args)
return wrapped
return wrapper
def async(f):
''' This decorator executes a function in a Thread'''
#wraps(f)
def wrapper(*args, **kwargs):
thr = threading.Thread(target=f, args=args, kwargs=kwargs)
thr.start()
return wrapper
#limit(10) # Always use #limit as the outter decorator
#async
def calcula_fatorial(number):
DIC.update({number: factorial(number)})
#limit(10)
def main(lista):
for elem in lista:
calcula_fatorial(elem)
if __name__ == '__main__':
from pprint import pprint
main(range(1000))
pprint(DIC)
I have recently posted a question about how to postpone execution of a function in Python (kind of equivalent to Javascript setTimeout) and it turns out to be a simple task using threading.Timer (well, simple as long as the function does not share state with other code, but that would create problems in any event-driven environment).
Now I am trying to do better and emulate setInterval. For those who are not familiar with Javascript, setInterval allows to repeat a call to a function every x seconds, without blocking the execution of other code. I have created this example decorator:
import time, threading
def setInterval(interval, times = -1):
# This will be the actual decorator,
# with fixed interval and times parameter
def outer_wrap(function):
# This will be the function to be
# called
def wrap(*args, **kwargs):
# This is another function to be executed
# in a different thread to simulate setInterval
def inner_wrap():
i = 0
while i != times:
time.sleep(interval)
function(*args, **kwargs)
i += 1
threading.Timer(0, inner_wrap).start()
return wrap
return outer_wrap
to be used as follows
#setInterval(1, 3)
def foo(a):
print(a)
foo('bar')
# Will print 'bar' 3 times with 1 second delays
and it seems to me it is working fine. My problem is that
it seems overly complicated, and I fear I may have missed a simpler/better mechanism
the decorator can be called without the second parameter, in which case it will go on forever. When I say foreover, I mean forever - even calling sys.exit() from the main thread will not stop it, nor will hitting Ctrl+c. The only way to stop it is to kill python process from the outside. I would like to be able to send a signal from the main thread that would stop the callback. But I am a beginner with threads - how can I communicate between them?
EDIT In case anyone wonders, this is the final version of the decorator, thanks to the help of jd
import threading
def setInterval(interval, times = -1):
# This will be the actual decorator,
# with fixed interval and times parameter
def outer_wrap(function):
# This will be the function to be
# called
def wrap(*args, **kwargs):
stop = threading.Event()
# This is another function to be executed
# in a different thread to simulate setInterval
def inner_wrap():
i = 0
while i != times and not stop.isSet():
stop.wait(interval)
function(*args, **kwargs)
i += 1
t = threading.Timer(0, inner_wrap)
t.daemon = True
t.start()
return stop
return wrap
return outer_wrap
It can be used with a fixed amount of repetitions as above
#setInterval(1, 3)
def foo(a):
print(a)
foo('bar')
# Will print 'bar' 3 times with 1 second delays
or can be left to run until it receives a stop signal
import time
#setInterval(1)
def foo(a):
print(a)
stopper = foo('bar')
time.sleep(5)
stopper.set()
# It will stop here, after printing 'bar' 5 times.
Your solution looks fine to me.
There are several ways to communicate with threads. To order a thread to stop, you can use threading.Event(), which has a wait() method that you can use instead of time.sleep().
stop_event = threading.Event()
...
stop_event.wait(1.)
if stop_event.isSet():
return
...
For your thread to exit when the program is terminated, set its daemon attribute to True before calling start(). This applies to Timer() objects as well because they subclass threading.Thread. See http://docs.python.org/library/threading.html#threading.Thread.daemon
Maybe these are the easiest setInterval equivalent in python:
import threading
def set_interval(func, sec):
def func_wrapper():
set_interval(func, sec)
func()
t = threading.Timer(sec, func_wrapper)
t.start()
return t
Maybe a bit simpler is to use recursive calls to Timer:
from threading import Timer
import atexit
class Repeat(object):
count = 0
#staticmethod
def repeat(rep, delay, func):
"repeat func rep times with a delay given in seconds"
if Repeat.count < rep:
# call func, you might want to add args here
func()
Repeat.count += 1
# setup a timer which calls repeat recursively
# again, if you need args for func, you have to add them here
timer = Timer(delay, Repeat.repeat, (rep, delay, func))
# register timer.cancel to stop the timer when you exit the interpreter
atexit.register(timer.cancel)
timer.start()
def foo():
print "bar"
Repeat.repeat(3,2,foo)
atexit allows to signal stopping with CTRL-C.
this class Interval
class ali:
def __init__(self):
self.sure = True;
def aliv(self,func,san):
print "ali naber";
self.setInterVal(func, san);
def setInterVal(self,func, san):
# istenilen saniye veya dakika aralığında program calışır.
def func_Calistir():
func(func,san); #calışıcak fonksiyon.
self.t = threading.Timer(san, func_Calistir)
self.t.start()
return self.t
a = ali();
a.setInterVal(a.aliv,5);