【发布时间】:2019-10-31 18:49:56
【问题描述】:
我有装饰器用作异常处理程序。我想优化它,因为与简单的 try...catch 相比,它慢了大约 6 倍。
我的装饰器的代码:
class ProcessException(object):
__slots__ = ('func', 'custom_handlers', 'exclude')
def __init__(self, custom_handlers=None):
self.func = None
self.custom_handlers: dict = custom_handlers
self.exclude = [QueueEmpty, QueueFull, TimeoutError]
def __call__(self, func):
self.func = func
return self.wrapper
def wrapper(self, *args, **kwargs):
if self.custom_handlers:
if isinstance(self.custom_handlers, property):
self.custom_handlers = self.custom_handlers.__get__(self, self.__class__)
if asyncio.iscoroutinefunction(self.func):
return self._coroutine_exception_handler(*args, **kwargs)
else:
return self._sync_exception_handler(*args, **kwargs)
async def _coroutine_exception_handler(self, *args, **kwargs):
try:
return await self.func(*args, **kwargs)
except Exception as e:
if self.custom_handlers and e.__class__ in self.custom_handlers:
return self.custom_handlers[e.__class__]()
if e.__class__ not in self.exclude:
raise e
def _sync_exception_handler(self, *args, **kwargs):
try:
return self.func(*args, **kwargs)
except Exception as e:
if self.custom_handlers and e.__class__ in self.custom_handlers:
return self.custom_handlers[e.__class__]()
if e.__class__ not in self.exclude:
raise e
作为基准,我将简单的函数与 try...catch 和函数与我的装饰器一起使用:
# simple function
def divide(a, b):
try:
return a // b
except ZeroDivisionError:
return 'error'
# function with decorator
@ProcessException({ZeroDivisionError: lambda: 'err'})
def divide2(a, b):
return a // b
简单函数 10000 次迭代的结果:
timeit.timeit('divide(1, 0)', number=10000, setup='from __main__ import divide')
0.010692662000110431
以及带有装饰器的功能:
timeit.timeit('divide2(1, 0)', number=10000, setup='from __main__ import divide2')
0.053688491000002614
请帮我优化一下,请解释瓶颈在哪里?
【问题讨论】:
-
从我的分析看来,大部分放缓似乎来自
if self.custom_handlers and e.__class__ in self.custom_handlers:。如果你真的在寻找效率,写一个装饰器可能不是要走的路。 -
@rassar 感谢您的评论。你的意思是装饰器总是会变慢吗?您能否澄清一下创建异常处理程序的最佳方法是什么?
-
嗯。仅仅通过拥有更多的线条,装饰者必须跳过更多的圈,因此需要更长的时间。此外,由于您希望能够指定异常和函数,因此解析和处理这些将花费更长的时间。您不太可能找到比您介绍的更快或更好的实现方式。
标签: python-3.x performance optimization python-decorators