Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
import time
def profile(function):
def wrapper(*args):
start_time = time.time()
function(*args)
end_time = time.time()
function.time_taken = end_time-start_time
return exec_time
return wrapper
"""
#profile
def calsqr(a,b):
return a**b
"""
#profile
def expensive_operation():
import time
time.sleep(3)
return 1
print(expensive_operation.time_taken)
assert expensive_operation() == 1
You need to assign time_taken to wrapper function, and first call it in order to be able to access time_taken variable
import time
def profile(function):
def wrapper(*args, **kwargs):
start_time = time.time()
ret_value = function(*args, **kwargs)
end_time = time.time()
wrapper.time_taken = end_time-start_time
return ret_value
return wrapper
"""
#profile
def calsqr(a,b):
return a**b
"""
#profile
def expensive_operation():
import time
time.sleep(3)
return 1
assert expensive_operation() == 1
print(expensive_operation.time_taken)
Related
This question already has answers here:
python decorator TypeError missing 1 required positional argument
(3 answers)
How to create a decorator that can be used either with or without parameters?
(16 answers)
Closed 2 years ago.
This is meant to calculate execution time and log / print it:
def timer(logger=None):
def decorator(func):
def wrapper(*args, **kwargs):
start_time = perf_counter()
result = func(*args, **kwargs)
total_time = perf_counter() - start_time
message = f'{func.__name__} Time: ' f'{total_time} seconds'
if logger is not None:
logger.info(message)
else:
print(message)
return result
return wrapper
return decorator
#timer
def decorated():
print("Running ...")
if __name__ == '__main__':
decorated()
I'm expecting this to print time, instead it complains about a missing argument:
TypeError: decorator() missing 1 required positional argument: 'func'
However, when I do:
#timer(None)
def decorated():
print("Running ...")
or:
#timer(logger=None)
def decorated():
print("Running ...")
It works! what is this nonsense?
Running ...
decorated Time: 2.3044999999999316e-05 seconds
Notes:
To those marking my question as a duplicate, can you explain why
other decorators work just fine?
In the example below, lru_cache accepts maxsize and typed parameters and works without explicit calls as well.
Example:
from functools import lru_cache
#lru_cache
def decorated():
print("Running ...")
Out:
Running ...
I tried to write a decorator to compute the time of the computation for methods in a class, but I also have a lot of properties.
I tried to write a decorator for a property as follows:
def timer(method):
import time
#property
def wrapper(*args, **kw):
start = time.time()
result = method
end = time.time()
print('Elapsed time for: {} is: {}s'.format(method.__name__,(end-start)*1000))
return result
return wrapper
I can't get the name of the property as written, moreover perhaps you would suggest to write it in another way?
You would need to stack decorators:
def timer(method):
import time
def wrapper(*args, **kwargs):
start = time.time()
result = method(*args, **kwargs) # note the function call!
end = time.time()
print('Elapsed time for: {} is: {}s'.format(method.__name__,(end-start)*1000))
return result
return wrapper
class X:
#property
#timer
def some_method(self):
# timed code
return 0
>>> x = X()
>>> x.some_method
Elapsed time for: some_method is: 0.0050067901611328125s
0
Could you please let me know if there is a way for a decorated function to keep its metadata?
This would be the code for the decorator:
def timer(func):
"""prints how long a function takes to run."""
def wrapper(*args, **kwargs):
t_start = time.time()
result = functionalists(*args, **kwargs)
t_total = time.time() - t_start
print('{} took {}s'.format(functionalists.__name__, t_total))
return result
return wrapper
The following would be the decorated function.
#timer
def sleep_n_seconds(n=10):
"""pause processing for n seconds.
Args:
n (int): The number of seconds to pause for.
"""
time.sleep(n)
When I try to print the docstrings with the following code, the metadata is not returned.
print(sleep_n_seconds.__doc__)
Please let me know if I need to provide further details.
Thank you
Use the wraps function from functools module to retain the signature. :
from functools import wraps
def timer(func):
#wraps(func)
"""prints how long a function takes to run."""
def wrapper(*args, **kwargs):
t_start = time.time()
result = functionalists(*args, **kwargs)
t_total = time.time() - t_start
print('{} took {}s'.format(functionalists.__name__, t_total))
return result
return wrapper
I have the below decorator function for printing response times. Is there a way to pass description of the decorator when decorating another function with this decorator? For eg: I want to print "calling service xyz" instead of function name "call_service_xyz"
def timer(func):
"""Print the runtime of the decorated function"""
#functools.wraps(func)
def wrapper_timer(*args, **kwargs):
start_time = time.perf_counter() # 1
value = func(*args, **kwargs)
end_time = time.perf_counter() # 2
run_time = end_time - start_time # 3
logger.info(f"Finished {func.__name__!r} in {run_time:.4f} secs")
return value
return wrapper_timer
#timer("call service xyz")
def call_service_xyz():
You could print the docstring to act as the description of the function:
def timer(func):
"""Print the runtime of the decorated function"""
#functools.wraps(func)
def wrapper_timer(*args, **kwargs):
start_time = time.perf_counter() # 1
value = func(*args, **kwargs)
end_time = time.perf_counter() # 2
run_time = end_time - start_time # 3
logger.info(f"{desc} Finished in {run_time:.4f} secs")
return value
return wrapper_timer
#timer
def call_service_xyz():
"""Call service xyz."""
# ^^ this is the docstring which is
# assigned to .__doc__
Alternatively, if you wish to pass the description into timer you need to create another layer to the decorator which accepts arguments:
def timer(desc):
def decorator(func):
#functools.wraps(func)
def wrapper_timer(*args, **kw):
start_time = time.perf_counter()
value = func(*args, **kw)
end_time = time.perf_counter()
run_time = end_time - start_time
logger.info(f"{func.__doc__!r} Finished in {run_time:.4f} secs")
return value
return wrapper_timer
return decorator
Now use as you describe in your question:
#timer('call service xyz')
def xyz():
...
This question already has answers here:
Read/Write Python Closures
(8 answers)
Closed 8 years ago.
I'm trying to write a decorator in Python to limit the number of times a function is called in an amount of time. I anticipate using it like this:
#ratelimit(seconds=15)
def foo():
print 'hello'
start = time.time()
while time.time() - start < 10:
foo()
> 'hello'
> 'hello'
So the decorated function can be called a maximum of once every seconds. In terms of implementing it I have this, but it doesn't work as I'm not sure the correct way to persist the last_call between subsequent calls:
import time
def ratelimit(seconds=10):
last_call = None # Never call decorated function
def decorator(func):
def wrapper(*args, **kwargs):
if last_call is None or time.time() - last_call > seconds:
result = func(*args, **kwargs)
last_call = time.time()
return result
return wraps(func)(wrapper)
return decorator
The code below worked fine for me in python 2.7.
import time
from functools import wraps
last_called = dict() # When last called, and with what result
def ratelimit(seconds=10, timer=time.time):
def decorator(func):
last_called[func] = None
#wraps(func)
def wrapper(*args, **kwargs):
now = timer()
call_data = last_called.get(func, None)
if call_data is None or now - call_data[0] >= seconds:
result = func(*args, **kwargs)
last_called[func] = (now, result)
else:
result = call_data[1] # Replay rate-limited result
return result
return wrapper
return decorator