Python/pickle

من موسوعة حسوب
مراجعة 14:44، 19 سبتمبر 2018 بواسطة Mohammed Taher (نقاش | مساهمات) (أنشأ الصفحة ب'تطبّق وحدة pickle بروتوكولات ثنائية لغرض سَلسلَة وإلغاء سَلسَلَة بنية كائنات بايثون. تطلق تسمي...')
(فرق) → مراجعة أقدم | المراجعة الحالية (فرق) | مراجعة أحدث ← (فرق)

تطبّق وحدة pickle بروتوكولات ثنائية لغرض سَلسلَة وإلغاء سَلسَلَة بنية كائنات بايثون. تطلق تسمية Pickling على العملية التي يتحوّل فيها تسلسل هرمي لكائن بايثون إلى تدفق بايتات byte stream، وتطلق تسمية Unpickling على العملية العكسية والتي يتحوّل فيها تدفّق بايتات (من ملف ثنائي أو كائن شبيه بالبايتات) إلى تسلسل هرمي لكائن بايثون.

تحمل هاتان العمليتان (Pickling و Unpickling) أسماءً أخرى مثل السَلسَلَة "serialization"، والترتيب "marshalling" (ليس المقصود هنا وحدة marshal) والتسطيح "falttening".

سنستخدم مصطلحي السلسلة وإلغاء السلسلة في هذا التوثيق كتعريب لمصطلحي pickling و unpickling.

تحذير لا تقدّم وحدة pickle الحماية تجاه البيانات المبنيّة على نحو خاطئ أو البيانات الخبيثة؛ لذا لا تلغِ سلسلة أي بيانات قادمة من مصادر غير موثوقة.

العلاقة التي تربط هذه الوحدة مع وحدات بايثون الأخرى

مقارنة الوحدة مع وحدة marshal

تمتلك بايثون وحدة سلسلة أكثر بساطة من وحدة pickle وتدعى وحدة marshal، ولكن يفضّل استخدام وحدة pickle بصورة عامة لإلغاء سلسلة كائنات بايثون، أما الهدف الرئيسي من وجود وحدة marshal هو دعم ملفات بايثون ذات الامتداد ‎.pyc.

تختلف وحدة pickle عن وحدة marshal في عدة نقاط:

  • تتابع وحدة pickle الكائنات التي تقوم بسلسلتها، وبهذا لن تؤدي الإشارة إلى الكائن نفسه إلى إعادة عملية السلسلة مرة أخرى. أما وحدة marshal لا تدعم ذلك.

لهذه الميزة تطبيقات في الكائنات التعاودية recursive وفي مشاركة الكائنات. الكائنات التعاودية هي كائنات تتضمن إشارات إلى نفسها، ولا يمكن التعامل مع مثل هذه الكائنات بواسطة وحدة marshal، وفي الواقع يؤدي استخدام هذه الوحدة مع الكائنات التعاودية إلى انهيار مفسّر بايثون. تحدث عملية مشاركة الكائن عند وجود إشارات متعددة لنفس الكائن في مواضع مختلفة من تسلسل الكائن الذي تجري سلسلته. تخزّن وحدة pickle مثل هذه الكائنات مرة واحدة، وتضمن أنّ جميع الإشارات الأخرى موجّهة نحو النسخة الأساسية. الكائنات المشتركة تبقى مشتركة، وهو أمر قد يكون في غاية الأهمية للكائنات القابلة للتعديل.

  • لا يمكن استخدام وحدة marshal لسلسلة الأصناف المعرّفة من قبل المستخدم إضافة إلى النسخ التابعة لها، أما وحدة pickle فبمقدورها أن تحفظ وتسترجع نسخ الصنف بطريقة واضحة، ولكن يجب أن يكون تعريف الصنف قابلًا للاستيراد وأن يكون موجودًا في نفس الوحدة كما هو الحال عند حفظ الكائن.

لا يمكن ضمان نقل صيغة السلسلة المعتمدة في وحدة marshal بين إصدارات بايثون المختلفة، والسبب في ذلك يعود إلى أنّ المهمّة الرئيسية لهذه الوحدة هو دعم ملفات ‎.pyc، وما من شيء يمكنه أن يفرض على مستخدمي بايثون عدم تغيير صيغة السلسلة بطريقة لا تكون متوافقة مع الإصدارات السابقة. في حين يمكن ضمان توافقية صيغة السلسلة المعتمدة في وحدة pickle مع الإصدارات السابقة من بايثون.

مقارنة pickle مع json

هناك عدد من الفروقات الجوهرية بين بروتوكول pickle وJSON (اختصار JavaScript Object Notation):

  • JSON هي صيغة لسلسلة النصوص (مخرجاتها هي نصوص بترميز unicode، وترمّز لاحقًا في معظم الأحيان إلى الترميز utf-8) في حين أنّ pickle هي صيغة لسلسلة البيانات الثنائية.
  • JSON قابلة للقراءة من قبل البشر، أما pickle فلا.
  • JSON واسعة الانتشار خارج بيئة بايثون، أما pickle فمخصّصة للغة بايثون فقط.
  • يمكن لـ JSON أن تمثّل -على نحو افتراضي- جزءًا من أنواع بايثون الداخلية، ولا تدعم الأصناف المخصصة، في حين أنّ بمقدور وحدة pickle أن تمثّل عددًا كبيرًا جدًا من أنواع بايثون (يمكن تمثيل الكثير من الأنواع تلقائيًا بواسطة بعض الأدوات التي تقدّمها بايثون، ويمكن تمثيل الحالات المعقّدة عن طريق تطبيق واجهات برمجية خاصّة ببعض الكائنات).

صيغة تدفق البيانات إنّ صيغة البيانات التي تستخدمها وحدة pickle خاصّة ببايثون، ومن حسنات ذلك عدم وجود أي قيود يمكن أن تفرض من مصادر خارجية مثل JSON أو XDR (والذي لا يمكنه تمثيل عملية مشاركة المؤشر)، ولكن ذلك يعني عدم قدرة البرامج المكتوبة بلغات أخرى من إعادة بناء كائنات بايثون المسَلسَلة.

تستخدم صيغة بيانات pickle تمثيلًا ثنائيًا مضغوطًا نسبيًا، وإن كنت مهتمًا بمسألة الحجم فيمكن ضغط البيانات المسَلسَلة بكفاءة عالية.

تتضمن وحدة pickletools أدوات لتحليل تدفق البيانات الناتجة من وحدة pickle، وتحتوي الشيفرة المصدرية لوحدة pickletools على تعليقات مكثفة حول شيفرات العمليات المستخدمة في بروتوكول pickle.

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

البروتوكول رقم 0 هو البروتوكول الأصلي الذي يمكن قراءته من قبل البشر وهو متوافق مع النسخ الأولى من بايثون.

البروتوكول رقم 1 هو صيغة ثنائية قديمة، وهو متوافق أيضًا مع النسخ الأولى من بايثون.

ُقدّم الإصدار 2.3 من بايثون البروتوكول رقم 2، ويوفّر هذا البروتوكول أصنافًا ذات شكل جديد لإجراء عمليات سلسلة ذات كفاءة أعلى. يمكن الرجوع إلى PEP 307 للاطلاع على المزيد من المعلومات حول التحسينات التي أتى بها البروتوكول رقم 2.

أضيف البروتوكول رقم 3 في الإصدار 3.0 من بايثون. يدعم هذا البروتوكول كائنات bytes صراحةً، ولا يمكن إلغاء سلسلته في إصدارات ‎2.x من اللغة، وهو البروتوكول الافتراضي وينصح باستخدامه عندما يكون التوافق مع إصدارات بايثون 3 الأخرى أمرًا مطلوبًا.

أضيف البروتوكول رقم 4 في الإصدار 3.4 من بايثون، ويدعم الكائنات ذات الأحجام الكبيرة، ويُتيح سَلسَلة أنواع إضافية من الكائنات، ويقدّم بعض التحسينات على صيغة البيانات. يمكن مراجعة PEP 3154 للاطلاع على التحسينات التي أتى بها البروتوكول رقم 4.

ملاحظة: إنّ مفهوم السَلسَلة Serialization مفهوم أكثر بدائية من الاستمرارية persistence، فبالرغم من أن pickle تقرأ كائنات الملفات وتكتب فيها، إلّا أنّها لا تعالج مسألة تسمية الكائنات المستمرة، ولا تعالج مشكلة الوصول المتزامن للكائنات المستمرة (وهي مشكلة أعقد بكثير).

يمكن لوحدة pickle أن تحول كائنًا معقدًا إلى تدفق بايتات وبمقدورها أن تحول تدفق بايتات إلى كائن يحمل البنية الداخلية نفسها، ولعلّ أوضح ما يمكن فعله بتدفق البايتات هذا هو كتابته في ملف، ولكن يمكن إرساله عبر شبكة معيّنة أو تخزينه في قاعدة بيانات. تقدّم وحدة shelve واجهة بسيطة لسَلسَلة وإلغاء سلسلة الكائنات في ملف قاعدة بيانات بنمط DBM.

الواجهة البرمجية للوحدة لا تتطلّب عملية سَلسَلة كائن معيّن سوى استدعاء الدالة dumps()‎، وكذلك الأمر في عملية إلغاء سَلسَلة تدفق بيانات معيّن، إذ يكفي استدعاء الدالة loads()‎. ولكن إن كنت بحاجة إلى التحكم بصورة أكبر على عملية السلسلة وإلغاء السلسلة، فيمكن إنشاء كائن Pickler أو Unpickler على التوالي.

تقدّم وحدة pickle الثوابت التالية:

pickle.HIGHEST_PROTOCOL

هذا الثابت هو عدد صحيح يعرض أعلى رقم متاح للبروتوكول، ويمكن تمرير هذا الثابت كقيمة للمعامل protocol في الدالتين dump()‎ و dumps()‎ إلى جانب الدالة البانية للكائن Pickler.

pickle.DEFAULT_PROTOCOL هذا الثابت هو عدد صحيح يمثّل النسخة الافتراضية من البروتوكول المستخدم في عملية السلسلة، ويمكن أن تكون قيمته أقل من قيمة الثابت HIGHEST_PROTOCOL. البروتوكول الافتراضي الحالي هو الرقم 3، وهو بروتوكول جديد صمّم للإصدار 3 من بايثون.