التسجيل Logging في البايثون – الدليل البسيط
برمجة تطبيق بلغة بايثون :
برمجة تطبيق بلغة بايثون : أهلاً بكم في بايثونات ونُرحب بكم في هذا المقال الجديد الذي نتكلم فيه عن موضوع التسجيل Logging في برامج البايثون.
من المهم معرفة ما يحدث خلال تنفيذ برنامج ما، وهذه الأهمية تظهر أثناء تطوير البرامج والنظم، وفي مرحلة الإختبار، وأيضًا خلال عمل هذه الأنظمة في البيئات الحقيقية والعملية، وتتنوع الطرق المُستخدمة في هذا الأمر من لغة برمجة إلى أخرى.
تُقدم لغة البرمجة البايثون وحدة مضمنة تلقائيًا عند تثبيت البايثون، وتُسمى هذه الوحدة ب Logging
وتحتوي على العديد من الوظائف التي تساعدك في تسجيل الأحداث خلال تنفيذ البرنامج بالإضافة لوجود مستويات من التسجيل تستطيع استخدامها حسب الحاجة.
نظرة عامة عن التسجيل في البايثون
التسجيل Logging مهم جدًا في عمل الأنظمة، وتقترن الأهمية بالخطورة عندما نتحدث عن أنظمة حساسة مثل أنظمة الطيران والمفاعلات النووية مثًلا، حيث يوجد في الطائرة ما يُسمى بالصندوق الأسود الذي يقوم بتسجيل كل المعلومات المهمة أثناء عملية الطيران، وفي حالة وجود خلل أو حادث سقوط للطائرة، يتم الرجوع لهذا الصندوق ومراجعة سجلاته.
في مجال البرمجيات والنظم، تُساعدك سجلات التسجيل في فهم عمل النظام ومراجعته في حال وجود خلل أو مشكلة. في ظل غياب عملية التسجيل، ستكون الخيارات محدودة وضيقة لفهم ما حدث أثناء فشل أو توقف نظام ما، ولا تقتصر أهمية التسجيل أثناء أو بعد حدوث مشكلة او خلل في النظام، بل تتجلى فوائده أيضا أثناء عملية تطوير وبناء البرمجيات وكذلك عملية اختبارها.
مستويات التسجيل
عند الحديث عن التسجيل في البرمجيات، فإننا نتكلم عن رسائل أو سجلات يتم حفظها أثناء عمل النظام في ملف خارجي منفصل عنه، ويتم تصنيف هذه الرسائل إلى مستويات رئيسية تندرج غالبًا تحت المُسميات التالية:
- INFO: التسجيلات التي تندرج تحت هذا التصنيف تُعتبر إعلامية (Informational Logs).
- :DEBUG وتعني أن السجلات هنا يتم توليدها بغرض إجراء عملية التنقيح (Debugging).
- WARNING: هنا يتم التعامل مع التسجيلات من منطلق تحذيري.
- ERROR: وتعني وجود أخطاء في النظام.
وحدة Logging في البايثون
تحتوي لغة البرمجة البايثون على وحدة Logging المعيارية المُضمنة تلقائيًا عند التثبيت، وتحتوي هذه الوحدة على العديد من الدوال والوظائف التي تتيح إجراء عملية تسجيل مُريحة وسلسلة عند بناء وتشغيل برامجك وأنظمتك بالبايثون.
تحتوي وحدة Logging في البايثون على خمسة مستويات للتسجيل هي بالترتيب: DEBUG، INFO، WARNING، ERROR، CRITICAL، وعند اختيار أحد هذه المستويات، فإن التسجيلات التي ستظهر هي تسجيلات المستوى الذي اخترته بالإضافة إلى تسجيلات جميع المستويات الأعلى، فمثلا، لو اخترنا مستوى ERROR عند تسجيل التسجيلات، فإن تسجيلات مستوى ERROR و CRITICAL هي التي سيتم توليدها. المستوى المستخدم بشكل تلقائي هو WARNING.
إنشاء مُسجل بسيط
إنشاء مُسجل (Logger) باستخدام المكتبة Logging هو أمر سهل ومباشر كما هو موضح في الشيفرة البرمجية التالية:
في البداية نقوم باستيراد الوحدة Logging ثم نستدعي الوظيفة basicConfig التي من خلالها نجهز اعدادات المُسجل وذلك باستخدام بعض المُعاملات مثل اسم الملف الذي سيتم حفظ التسجيلات فيه، مستوى التسجيل وتنسيق التسجيلات وغيره من الإعدادات.
الأسطر التي تلي إعداد المُسجل هي أمثلة لطريقة استخدام مكتبة التسجيل لتوليد تسجيلات في الملف الذي قمنا بإعداده باسم log_file.log وكل سطر يُمثل مستوى تسجيل من المستويات التي ذكرناها سابقا.
عند تنفيذ الشيفرة السابقة أول مرة، سيكون محتوى الملف log_file.log كالتالي:
WARNING:root:Simple logging – Warning record
ERROR:root:Simple logging – Error record
CRITICAL:root:Simple logging – Critical record
كما ذكرنا سابقًا، فإن المستوى التلقائي للتسجيل هو Warning وهذا يعني أن جميع التسجيلات من هذا المستوى فأعلى هي التي سيتم توليدها.
لتغيير المستوى لمستوى التنقيح Debug نقوم بإضافة المعامل level للوظيفة basicConfig ونقوم بإعطائه القيمة logging.DEBUG.
نستطيع استخدام مكتبة التسجيل في تسجيل الأخطاء التي تظهر أثناء عمل برنامج البايثون. الشيفرة التالية توضح ذلك:
عند تنفيذ raise RuntimeError سيتم معالجة الخطأ وتنفيذ اخر سطر في الشيفرة، والذي بدوره سيقوم بإضافة تسجيل في الملف log_file2.log من نوع ERROR بالإضافة لتفاصيل الخطأ الذي ظهر.
التسجيل متعدد الأمكنة
كلما زاد حجم الشيفرة البرمجية كلما زادت الحاجة لتوزيع الشيفرة في أكثر من وحدة برمجية وأكثر من ملف.
التسجيل من أماكن متعددة في البايثون هو أمر مهم، وسنحتاج لتطبيق ذلك أن نُعَرف المُسجل من خلال الوظيفة getLogger والتي تُساعد في القيام بإعدادات مختلفة للتسجيل من ضمنها معرفة مصدر التسجيل.
لنفترض أنه يوجد لدينا برنامج بايثون يتكون من ملفين، الأول باسم main_Prog.py وهو الملف الرئيسي للبرنامج، والملف الثاني باسم sub_Prog.py ويحتوي على بعض الوظائف التي نريد استخدامها في الملف الرئيسي.
الشيفرة البرمجية للملف main_Prog:
الشيفرة البرمجية للملف sub_Prog:
في الشيفرة البرمجية للملف main_Prog قمنا بتعريف المُسجل من خلال الوظيفة getLogger ومن خلالها يُمكننا إعطاء عنوان أو اسم للمُسجل، وهذا يعني أننا نستطيع إنشاء أكثر من مُسجل وأن نقوم بإعداد كل مُسجل على حدة من حيث تحديد ملف التسجيلات، تنسيق التسجيلات وكيفية ظهورها في ملف التسجيلات وغيرها من الإعدادات.
السطر التالي نستخدمه لإنشاء مسجل باسم Main_Program:
في السطر السابق قمنا بحفظ المُسجل في متغير باسم main_logger ولكن Main_Program هو اسم المُسجل نفسه الذي سيظهر في ملف التسجيلات.
لتحديد ملف التسجيلات الخاص بالمسجل نستخدم الوظيفة logging.FileHandler ومن ثم نستخدم الوظيفة addHandler الخاصة بالمُسجل لإضافة المعالج “Handler” إليه.
لتحديد شكل الرسائل التي تظهر في ملف التسجيلات نستخدم الوظيفة logging.Formatter في بناء التنسيق الذي نريده، ومن ثم نقوم باستخدام الوظيفة setFormatter الخاصة بالمُسجل لإضافة هذا التنسيق.
في موضوع التسجيل متعدد الأمكنة، لاحظ معي أننا قمنا بإعداد المُسجل الرئيسي في الملف main_Prog وحددنا شكل التسجيلات، ولكن في الملف الفرعي sub_Prog قمنا فقط بتعريف المُسجل logger. عند تشغيل الملف الرئيسي ستظهر التسجيلات في الملف بالشكل التالي:
2018-04-21 11:30:09,822 – Main_Program – INFO – System Lunched
2018-04-21 11:30:09,822 – Main_Program.Sub_Program.print_name – INFO – Name printed
2018-04-21 11:30:09,823 – Main_Program – INFO – End
الرسالة الأولى والثالثة تم توليدهما من خلال المسجل Main_Program الموجود في الملف الرئيسي main_Prog والرسالة الثانية تم توليدها من خلال المُسجل Main_Program.Sub_Program.print_name الموجود في الملف الفرعي sub_Prog.
خاتمة
التسجيل Logging هو أحد أهم الوسائل المُستخدمة في معرفة ما يحدث خلال عمل برنامج البايثون، بالإضافة إلى أنه يساعد في عملية التنقيح ومعرفة المشاكل ومكان حدوثها. في هذا المقال تعرفنا على أهمية التسجيل وما هي مستوياته وشرحنا مثالًا عن كيفية تهيئة المُسجل وكيفية عمل التسجيل من عدة ملفات.
[…] في الكثير من التطبيقات التي نبنيها أن نُفعل خاصية التسجيل Logging في بايثون لو أردنا أن نُراقب الدالة sleepy في المثال السابق، بحيث […]