Python v3.x: معالج استثناء لوظائف coroutine و متزامن. بشكل عام ، على كل شيء

في وقت فراغي أعمل على مشروعي الصغير . مكتوب في بيثون v3.x + SQLAlchemy. ربما سأكتب عنه يومًا ما ، لكن اليوم أريد أن أتحدث عن مصمم الديكور الخاص بي لمعالجة الاستثناءات. يمكن استخدامه لكل من الوظائف والأساليب. متزامن وغير متزامن. يمكنك أيضًا الاتصال بمعالجات الاستثناء المخصصة.

يبدو الديكور حاليًا كما يلي:
import asyncio from asyncio import QueueEmpty, QueueFull from concurrent.futures import TimeoutError 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, *a): self.func = func def wrapper(*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) return wrapper 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 

سوف نحلل بالترتيب. __slots__ يمكنني استخدامها لحفظ القليل من الذاكرة. من المفيد إذا تم استخدام الكائن في كثير من الأحيان.

في مرحلة التهيئة في __init__ ، نقوم بحفظ custom_handlers (في حال كان من الضروري نقلها). فقط في حالة ، أشار إلى أننا نتوقع أن نرى قاموسًا هناك ، على الرغم من أنه ، ربما في المستقبل ، من المنطقي أن نضيف بعض الاختبارات الشاقة. تحتوي الخاصية self.exclude على قائمة الاستثناءات التي لا تحتاج إلى معالجة. في حالة حدوث مثل هذا الاستثناء ، فإن الوظيفة مع الديكور ستعود بلا. في الوقت الحالي ، يتم تشديد القائمة لمشروعي ، وربما يكون من المنطقي وضعه في تكوين منفصل.

أهم شيء يحدث في __call__. لذلك ، عند استخدام الديكور ، تحتاج إلى تسميته. حتى بدون معلمات:

 @ProcessException() def some_function(*args): return None 

أي سيكون هذا خطأ وسيتم رفع خطأ:

 @ProcessException def some_function(*args): return None 

في هذه الحالة ، نحصل على الوظيفة الحالية ، والتي ، وفقًا لدرجة عدم تزامنها ، سوف نعالجها إما كمتزامن منتظم أو كوروتين.

ما يمكنك الانتباه إلى هنا. الأول هو التحقق من الممتلكات:

 if self.custom_handlers: if isinstance(self.custom_handlers, property): self.custom_handlers = self.custom_handlers.__get__(self, self.__class__) 

لماذا أفعل هذا؟

 بالطبع 
          ليس بسبب 
                       أنا ماياكوفسكي 
                                    ويدفعون لي سطرا سطرا.

اثنان إذا كانا هنا لتحسين قابلية القراءة (نعم ، لأنه يمكن دعم الكود من قبل شخص لديه ميول سادية) ، ونحن نفعل self.custom_handlers. معالجات المخزنة في فئةproperty.

على سبيل المثال ، مثل هذا:

 class Math(object): @property def exception_handlers(self): return { ZeroDivisionError: lambda: '   ,   ' } @ProcessException(exception_handlers) def divide(self, a, b): return a // b 

إذا لم ننفذ self.custom_handlers .__ get __ (...) ، فبدلاً من محتوياتproperty ، سنحصل على شيء مثل <property property في 0x7f78d844f9b0>.

في الواقع ، يوضح المثال أعلاه كيفية توصيل معالجات مخصصة. بشكل عام ، يتم ذلك على النحو التالي:

 @ProcessException({ZeroDivisionError: lambda: '   ,   '}) def divide(a, b): return a // b 

في حالة وجود فصل (إذا كنا سنجتاز الخصائص / الطرق) ، يجب أن نأخذ في الاعتبار أنه في مرحلة تهيئة مصمم الفصل على هذا النحو ، فإن الطرق والخصائص ليست وظائف بسيطة. لذلك ، يمكننا فقط نقل ما أعلن أعلاه. لذلك ، فإن خيارproperty هو القدرة على استخدام جميع الوظائف الأقل في الشفرة من خلال الذات. حسنًا ، يمكنك استخدام lambdas إذا لم تكن هناك حاجة إلى النفس.

لرمز غير متزامن ، كل الأمثلة المذكورة أعلاه صحيحة.

في النهاية ، أود أن ألفت الانتباه إلى حقيقة أنه إذا لم يجتمع استثناء معالجات مخصصة في طريقها ، فسوف يرتفع ببساطة.

في انتظار تعليقاتكم. شكرا لك على الاهتمام بمقالتي.

Source: https://habr.com/ru/post/ar473596/


All Articles