معالجة الأخطاء
التسلسل الهرمي للاستثناءات، وسمات الأخطاء، وأخطاء حمولة HTTP 200، والتحقق من جانب العميل، وإرشادات إعادة المحاولة في Python SDK لـ Listings API.
يمكن استيراد جميع الاستثناءات من الوحدة listingsapi ذات المستوى الأعلى.
التسلسل الهرمي للاستثناءات
ListingsAPIError├── APIError API-reported failure: non-2xx, or an error payload in HTTP 200│ ├── AuthenticationError 401, or payload codes SY90005 / SY90001│ ├── PermissionDeniedError 403, or payload code SY90003│ ├── NotFoundError 404│ ├── ValidationError 400 / 422, mutation failures, client-side validation│ ├── RateLimitError 429, or payload code RATE_LIMITED (carries .retry_after)│ └── InternalServerError 5xx (safe to retry)└── APIConnectionError network failure: DNS, connection refused, timeoutالتقط ListingsAPIError لمعالجة كل ما قد تثيره حزمة SDK، أو APIError لمعالجة كل ما أبلغت عنه واجهة API، أو فئة فرعية محددة لمعالجة حالات بعينها.
خصائص الاستثناءات
يتضمن APIError وفئاته الفرعية ما يلي:
يرث APIConnectionError مباشرةً من ListingsAPIError ولا يتضمن أيًا من هذه الخصائص؛ وتصف رسالة الاستثناء فشل الشبكة.
التقاط الاستثناءات
import listingsapi client = listingsapi.ListingsAPI() try: location = client.locations.retrieve(16808)except listingsapi.AuthenticationError as e: print("Invalid API key:", e.code)except listingsapi.PermissionDeniedError as e: print("Not allowed:", e.status_code)except listingsapi.NotFoundError as e: print("No such location:", e.status_code)except listingsapi.ValidationError as e: for err in e.errors: print(err["code"], err["message"], err["context"])except listingsapi.RateLimitError as e: print("Rate limited, retry in", e.retry_after, "seconds")except listingsapi.InternalServerError as e: print("Server error (safe to retry):", e.status_code)except listingsapi.APIConnectionError as e: print("Network failure:", e)except listingsapi.APIError as e: print("Unexpected API error:", e.status_code, e.code, e.response_body)الأخطاء داخل استجابات HTTP 200
تُبلغ المنصة أحيانًا عن حالات فشل داخل جسم استجابة 200. تفحص حزمة SDK كل استجابة وتثير الاستثناءات، لذا لا تحتاج أبدًا إلى التحقق من أعلام success أو فحص مصفوفات errors بنفسك:
- تُحوَّل أجسام
errors[]ذات المستوى الأعلى إلى استثناءات حسب الرمز: يؤدي كل منSY90005وSY90001إلى إثارةAuthenticationError، ويؤديSY90003إلى إثارةPermissionDeniedError، ويؤديRATE_LIMITEDإلى إثارةRateLimitError، ويؤدي أي رمز آخر إلى إثارةAPIError. - تؤدي استجابات عمليات الكتابة (الإنشاء والتحديث والأرشفة ونشر المنشورات) التي تتضمن
success: falseأو قائمةerrors[]إلى إثارةValidationError.
في كلتا الحالتين، يمثّل status_code حالة HTTP الفعلية (غالبًا 200)، ويمثّل code أول رمز من المنصة، ويحتوي errors على جميع العناصر بصيغتها الموحّدة:
import listingsapi client = listingsapi.ListingsAPI() try: result = client.locations.update({"id": 16808, "phone": "not-a-phone"})except listingsapi.ValidationError as e: print(e.status_code) # 200: the API accepted the request but rejected the mutation print(e.code) # first platform code, e.g. "SY10005" for err in e.errors: print(err["code"], err["message"], err["context"])التحقق من الصحة من جانب العميل
يتحقق locations.add() والدوال المساعدة للمنشورات (posts.create_announcement() وposts.create_event() وposts.create_offer() وposts.bulk_publish()) من صحة حمولتها محليًا وتثير ValidationError قبل إجراء أي استدعاء عبر الشبكة، لذا تؤدي الحمولة غير الصالحة إلى فشل فوري مع رسالة واضحة بدلًا من إرسال طلب وانتظار استجابة.
بالنسبة إلى locations.add():
- يجب أن يتراوح طول
nameبين 2 و150 حرفًا - يجب ألا يقل طول
descriptionعن 200 حرف sub_category_idمطلوبcountry_isoمطلوبcityمطلوب ما لم يتحققhide_address=True(الأنشطة التجارية التي تخدم نطاقًا جغرافيًا)
بالنسبة إلى الدوال المساعدة للمنشورات:
nameمطلوب ويجب ألا يكونlocation_idsفارغًا- يجب أن يكون
sitesمجموعة فرعية غير فارغة منGOOGLE،FACEBOOK messageمطلوب؛ وعندما يكون قاموسًا يخصص قيمة لكل موقع، يجب توفير نص لكل موقع مستهدف- يجب توفير
cta_typeوcta_urlمعًا، ويجب أن يكونcta_typeإحدى القيم التالية:BOOK،ORDER،SHOP،LEARN_MORE،SIGN_UP،GET_OFFER titleمطلوب للفعاليات والعروض
في هذه الأخطاء التي تُثار محليًا، تكون قيمة كل من status_code وcode وresponse_body هي None، ويكون errors فارغًا؛ ويسرد str(e) جميع المشكلات التي عُثر عليها:
import listingsapi client = listingsapi.ListingsAPI() try: client.locations.add( name="Acme Dental", description="Too short.", sub_category_id=1432, country_iso="US", city="New York", )except listingsapi.ValidationError as e: print(e) # Invalid location: description must be at least 200 characters (got 10) print(e.status_code) # None: raised before any network callإعادة المحاولة تلقائيًا
تعيد حزمة SDK المحاولة تلقائيًا عند حدوث 429 و500 و502 و503 و504 لطلبات GET وHEAD وOPTIONS (افتراضيًا، 2 محاولات إعادة، ومعامل تأخير أُسّي قدره 0.5 ثانية، مع الالتزام بـ Retry-After). لا تُعاد محاولة عمليات الكتابة: يُرسل طلب POST أو DELETE مرة واحدة ويُثار استثناء عند أول فشل. اضبط ذلك باستخدام وسيط المُنشئ max_retries؛ راجع الإعدادات.
لا تدعم واجهة API بالإصدار v4 ميزة Idempotency-Key ولا تكتشف عمليات الكتابة المكررة، لذا قد تكون عملية الكتابة التي تنتهي مهلتها أو تُرجع 5xx قد حُفظت بالفعل. ستؤدي إعادة محاولتها دون تحقق إلى إنشاء موقع ثانٍ أو منشور ثانٍ أو رد ثانٍ على تقييم. اقرأ السجل مجددًا باستخدام مفتاح تتحكم فيه قبل تكرار عملية الكتابة.
تأخير إعادة المحاولة عند حدوث RateLimitError
عندما يستمر حدوث 429 بعد محاولات الإعادة المدمجة، يحتوي RateLimitError.retry_after على قيمة Retry-After التي أرسلها الخادم بالثواني (أو None إذا كانت الترويسة غائبة). مثال بسيط لمهام المعالجة الدفعية:
import randomimport time import listingsapi client = listingsapi.ListingsAPI(max_retries=0) # manual retry control def with_backoff(call, max_attempts=5): for attempt in range(max_attempts): try: return call() except listingsapi.RateLimitError as e: if attempt == max_attempts - 1: raise if e.retry_after is not None: delay = e.retry_after else: delay = min(2 ** attempt, 30) + random.random() time.sleep(delay) page = with_backoff(lambda: client.locations.list(first=50))for location in page: print(location.name)استيراد الاستثناءات
# All exceptions from the top-level moduleimport listingsapi listingsapi.ListingsAPIErrorlistingsapi.APIErrorlistingsapi.AuthenticationErrorlistingsapi.PermissionDeniedErrorlistingsapi.NotFoundErrorlistingsapi.ValidationErrorlistingsapi.RateLimitErrorlistingsapi.InternalServerErrorlistingsapi.APIConnectionError # Or import individuallyfrom listingsapi import RateLimitError, ValidationErrorانظر أيضًا
- الإعدادات:
max_retriesوtimeout - البدء السريع: أول برنامج نصي لك يتضمن معالجة الأخطاء