الوحدة shelve
في بايثون
الرف shelf
هو كائن مستمر persistent شبيه بالقاموس، ويختلف عن قواعد بيانات "dbm" في أنّ القيم (وليست المفاتيح) في الرفّ يمكن أن تكون من أيّ نوع من أنواع بيانات بايثون، وبمعنى أدق أيّ نوع يمكن لوحدة pickle
أن تتعامل معه، وهذا يتضمّن معظم نسخ الأصناف، وأنواع البيانات التعاودية، والكائنات التي تتضمن الكثير من الكائنات الفرعية المشتركة. تكون المفاتيح في الرفوف سلاسل نصية عادية.
تحذير: نظرًا لاستناد الرفوف على وحدة pickle
، فإنّ من الخطر أن تحمّل رفًّا من مصادر غير موثوقة. وكما هو الحال مع وحدة pickle
، يمكن لعملية تحميل الرفّ أن تنفّذ أيّ نوع من الشيفرات.
دوال الوحدة shelve
تقدّم وحدة shelve دالة واحدة فقط:
الدالة shelve.open()
تفتح الدالة قاموسًا مستمرًّا (رفًّا).
تدعم كائنات Shelf
جميع التوابع التي تدعمها القواميس، وهذا يسهّل الانتقال من الشيفرات المبنية على القواميس إلى الشيفرات التي تتطلب تخزين البيانات بصورة مستمرة، وتدعم إلى جانب ذلك تابعين إضافيين هما:
sync()
يعيد التابع كتابة جميع المدخلات في الذاكرة المخبيئة إذا فُتح الرفّ مع إعطاء المعامل writeback
القيمة True
. يفرّغ هذا التابع كذلك الذاكرة المخبئية ويزامن القاموس المستمر على القرص الصلب إن كان ذلك ممكنًا. يستدعى هذا التابع تلقائيًا عند إغلاق الرفّ بواسطة الدالة close()
.
close()
يزامن التابع ويغلق كائن dict
المستمر. يؤدي إجراء أي عملية على كائن Shelf
مغلق إلى إطلاق الخطأ ValueError
.
القيود
- يعتمد اختيار حزمة قاعدة البيانات (مثل
dbm.ndbm
أوdbm.gnu
) على الواجهة البرمجية المتوفّرة؛ ولهذا ليس من الآمن فتح قاعدة البيانات باستخدامdbm
مباشرة. تكون قاعدة البيانات كذلك عرضة لمحدّداتdbm
في حال استخدامها، وهذا يعني أنّه يجب أن تكون الكائنات (والتمثيل المسلسل لها) ذا حجم صغيرٍ نسبيًا، وفي بعض الحالات النادرة يؤدي التضارب بين المفاتيح إلى رفض قاعدة البيانات لتحديث البيانات. - لا تدعم وحدة
shelve
عمليات الكتابة والقراءة المتزامنة في الكائنات المرفوفة shelved objects. (عمليات القراءة المتعددة والمتزامنة أكثر أمانًا). عندما يفتح برنامج رفًّا للكتابة، يجب أن لا يفتح أي برنامج آخر ذلك الرفّ للقراءة أو للكتابة. يمكن استخدام خاصية قفل الملفات في يونكس لحل هذه المشكلة، ولكنّ هذه التقنية متفاوتة بين إصدارات يونكس وتتطلب معرفة الأداة المستخدمة للتعامل مع قاعدة البيانات.
أصناف الوحدة shelve
الصنف shelve.Shelf
صنف متفرّع من الصنف collections.abc.MutableMapping
مهمّته تخزين القيم المسلسلة في كائن dict
المعطى.
الصنف shelve.BsdDbShelf
صنف متفرّع من الصنف Shelf
ويقدّم التوابع first()
و next()
و previous()
و last()
و set_location()
وهي متوفّرة في الوحدة bsddb
من pybsddb
ولكن ليس في وحدات قواعد البيانات الأخرى.
الصنف shelve.DbfilenameShelf
صنف متفرّع من الصنف Shelf
ويأخذ ملفًّا عوضًا عن كائن شبيه بالقاموس.
أمثلة
يوضّح المثال التالي الواجهة البرمجية لهذه الوحدة (المفتاح سلسلة نصية، والبيانات كائنات متنوعة):
import shelve
d = shelve.open(filename) # فتح الرف - يمكن لاسم الملف أن يأخذ لاحقة بواسطة مكتبات
# المستوى الواطئ
d[key] = data # تخزين البيانات في المفتاح (تمسح البيانات القديمة
# في حال استخدام مفتاح موجود أصلًا).
data = d[key] # استراجع نسخة من البيانات الموجودة في المفتاح
# يطلق الاستثناء KeyError في حال عدم وجود المفتاح
del d[key] # حذف البيانات الموجودة في المفتاح
# يطلق الاستثناء KeyError في حال عدم وجود المفتاح
flag = key in d # العبارة صحيحة إن كان المفتاح موجودًا
klist = list(d.keys()) # قائمة بجميع المفاتيح الموجودة (عملية بطيئة!)
# يجب الانتباه إلى ما يلي إذا كان d مفتوحًا دون writeback=True
d['xx'] = [0, 1, 2] # تعمل هذه الشيفرة كما هو متوقع
d['xx'].append(3) # *ولكن هذه لا* -- d['xx'] مازالت [0, 1, 2]!
# في حال عدم استخدام writeback=True يجب كتابة الشيفرة بحذر:
temp = d['xx'] # استخراج النسخة
temp.append(5) # تعديل النسخة
d['xx'] = temp # تخزين النسخة من جديد لجعلها مستمرة
# أو يمكن استخدام d=shelve.open(filename,writeback=True) والتي تسمح باستخدام الشيفرة
# d['xx'].append(5) وستعمل كما هو متوقع، ولكنّها قد تستهلك المزيد من الذاكرة
# وتصبح عملية إغلاق الكائن أبطأ.
d.close() # إغلاق الكائن