J'essaye de faire un décorateur pour envelopper des coroutines ou des fonctions.Comment créer un décorateur Python qui peut envelopper la coroutine ou la fonction?
La première chose que j'ai essayé était un simple code en double dans des emballages:
def duration(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start_ts = time.time()
result = func(*args, **kwargs)
dur = time.time() - start_ts
print('{} took {:.2} seconds'.format(func.__name__, dur))
return result
@functools.wraps(func)
async def async_wrapper(*args, **kwargs):
start_ts = time.time()
result = await func(*args, **kwargs)
dur = time.time() - start_ts
print('{} took {:.2} seconds'.format(func.__name__, dur))
return result
if asyncio.iscoroutinefunction(func):
return async_wrapper
else:
return wrapper
Cela fonctionne, mais je veux éviter la duplication de code, car ce n'est pas beaucoup mieux que d'écrire deux décorateurs séparés.
Alors j'ai essayé de faire un décorateur classe en utilisant:
class SyncAsyncDuration:
def __init__(self):
self.start_ts = None
def __call__(self, func):
@functools.wraps(func)
def sync_wrapper(*args, **kwargs):
self.setup(func, args, kwargs)
result = func(*args, **kwargs)
self.teardown(func, args, kwargs)
return result
@functools.wraps(func)
async def async_wrapper(*args, **kwargs):
self.setup(func, args, kwargs)
result = await func(*args, **kwargs)
self.teardown(func, args, kwargs)
return result
if asyncio.iscoroutinefunction(func):
return async_wrapper
else:
return sync_wrapper
def setup(self, func, args, kwargs):
self.start_ts = time.time()
def teardown(self, func, args, kwargs):
dur = time.time() - self.start_ts
print('{} took {:.2} seconds'.format(func.__name__, dur))
qui fonctionne dans certains cas, très bien pour moi, mais dans cette solution, je ne peux pas mettre une fonction avec ou essayer déclarations. Puis-je créer un décorateur sans dupliquer le code?
Merci beaucoup, c'est exactement ce je cherchais. –