shelve --- ماندگاری اشیاء در پایتون

کد منبع: Lib/shelve.py


یک «قفسه» (shelf) شیء پایا و دیکشنری‌مانند است. تفاوت آن با پایگاه‌های داده «dbm» در این است که مقادیر (نه کلیدها!) در یک قفسه می‌توانند اساساً اشیاء پایتونی دلخواهی باشند — هر چیزی که ماژول pickle بتواند آن را مدیریت کند. این شامل بیشتر نمونه‌های کلاس، انواع داده بازگشتی و اشیایی می‌شود که حاوی تعداد زیادی زیرشیء مشترک هستند. کلیدها رشته‌های معمولی هستند.

shelve.open(filename, flag='c', protocol=None, writeback=False, *, serializer=None, deserializer=None)

یک دیکشنری پایا را باز می‌کند. نام پرونده مشخص‌شده، نام پرونده پایه برای پایگاه داده‌ی زیربنایی است. به‌عنوان اثر جانبی، ممکن است پسوندی به نام پرونده اضافه شود و بیش از یک پرونده ایجاد شود. به‌طور پیش‌فرض، پرونده پایگاه داده‌ی زیربنایی برای خواندن و نوشتن باز می‌شود. پارامتر اختیاری flag همان تفسیر پارامتر flag در dbm.open() را دارد.

به‌طور پیش‌فرض، پیکل‌های ایجادشده با pickle.DEFAULT_PROTOCOL برای سریال‌سازی مقادیر استفاده می‌شوند. نسخه‌ی پروتکل پیکل را می‌توان با پارامتر protocol مشخص کرد.

به دلیل معناشناسی پایتون، یک shelf نمی‌تواند بداند چه زمانی یک آیتم تغییرپذیر در دیکشنری پایا تغییر می‌کند. به‌طور پیش‌فرض، اشیای تغییرکرده فقط زمانی نوشته می‌شوند که به shelf انتساب داده شوند (به مثال مراجعه کنید). اگر پارامتر اختیاری writeback روی True تنظیم شود، همه آیتم‌های دسترسی‌یافته نیز در نهانگاه حافظه ذخیره می‌شوند و در sync() و close() بازنویسی می‌شوند؛ این موضوع می‌تواند تغییر دادن آیتم‌های تغییرپذیر در دیکشنری پایا را آسان‌تر کند، اما اگر به آیتم‌های زیادی دسترسی پیدا شود، می‌تواند حجم بسیار زیادی از حافظه را برای نهانگاه مصرف کند و عملیات close را بسیار کند سازد، زیرا همه آیتم‌های دسترسی‌یافته بازنویسی می‌شوند (هیچ راهی برای تشخیص اینکه کدام آیتم‌های دسترسی‌یافته تغییرپذیرند، و نه اینکه کدام‌یک واقعاً تغییر کرده‌اند، وجود ندارد).

By default, shelve uses pickle.dumps() and pickle.loads() for serializing and deserializing. This can be changed by supplying serializer and deserializer, respectively.

The serializer argument must be a callable which takes an object obj and the protocol as inputs and returns the representation obj as a bytes-like object; the protocol value may be ignored by the serializer.

The deserializer argument must be a callable which takes a serialized object given as a bytes object and returns the corresponding object.

A ShelveError is raised if serializer is given but deserializer is not, or vice-versa.

تغییر یافته در نسخه‌ی 3.10: pickle.DEFAULT_PROTOCOL اکنون به‌عنوان پروتکل پیش‌فرض pickle استفاده می‌شود.

تغییر یافته در نسخه‌ی 3.11: path-like object را برای نام پرونده می‌پذیرد.

تغییر یافته در نسخه‌ی 3.15: Accepts custom serializer and deserializer functions in place of pickle.dumps() and pickle.loads().

توجه

به بسته شدن خودکار قفسه (shelf) اتکا نکنید؛ همیشه وقتی دیگر به آن نیاز ندارید، close() را به‌صراحت فراخوانی کنید، یا از shelve.open() به‌عنوان مدیر زمینه استفاده کنید:

with shelve.open('spam') as db:
    db['eggs'] = 'eggs'

هشدار

از آن‌جا که ماژول shelve بر پایه pickle است، بارگذاری یک قفسه (shelf) از یک منبع غیرقابل‌اعتماد امن نیست. مانند pickle، بارگذاری یک قفسه (shelf) می‌تواند کد دلخواه را اجرا کند.

اشیای Shelf از بیشتر متدها و عملیات‌هایی که دیکشنری‌ها پشتیبانی می‌کنند، پشتیبانی می‌کنند (به‌جز کپی‌سازی، سازنده‌ها و عملگرهای | و |=). این کار گذار از اسکریپت‌های مبتنی بر دیکشنری به اسکریپت‌های نیازمند ذخیره‌سازی پایا را آسان می‌کند.

از دو متد اضافی پشتیبانی می‌شود:

Shelf.sync()

Write back all entries in the cache if the shelf was opened with writeback set to True. Also empty the cache and synchronize the persistent dictionary on disk, if feasible. This is called automatically when reorganize() is called or the shelf is closed with close().

Shelf.reorganize()

Calls sync() and attempts to shrink space used on disk by removing empty space resulting from deletions.

اضافه شده در نسخه‌ی 3.15.

Shelf.close()

همگام‌سازی و بستن شیء dict پایا. عملیات روی یک shelf بسته با ValueError شکست خواهد خورد.

همچنین ملاحظه نمائید

دستور دیکشنری پایا با قالب‌های ذخیره‌سازی با پشتیبانی گسترده و دارای سرعت دیکشنری‌های بومی.

محدودیت‌ها

  • انتخاب بسته‌ی پایگاه داده‌ای که استفاده خواهد شد (مانند dbm.ndbm یا dbm.gnu) به این بستگی دارد که کدام رابط در دسترس باشد. بنابراین باز کردن پایگاه داده به‌صورت مستقیم با استفاده از dbm ایمن نیست. پایگاه داده نیز (متأسفانه) در صورت استفاده از dbm مشمول محدودیت‌های آن است — این بدان معناست که بازنمایی pickleشده (pickled representation) از اشیاء ذخیره‌شده در پایگاه داده باید نسبتاً کوچک باشد، و در موارد نادر ممکن است برخورد کلیدها باعث شود پایگاه داده از پذیرفتن به‌روزرسانی‌ها خودداری کند.

  • ماژول shelve از دسترسی همزمان خواندن/نوشتن به اشیای ذخیره‌شده در shelf پشتیبانی نمی‌کند. (چندین دسترسی خواندن همزمان بی‌خطر است.) هنگامی که برنامه‌ای یک shelf را برای نوشتن باز نگه داشته است، هیچ برنامه دیگری نباید آن را برای خواندن یا نوشتن باز نگه دارد. می‌توان از قفل‌گذاری پرونده در یونیکس برای حل این مسئله استفاده کرد، اما این رفتار در نسخه‌های مختلف یونیکس متفاوت است و به دانش درباره‌ی پیاده‌سازی پایگاه داده‌ی استفاده‌شده نیاز دارد.

  • در macOS، dbm.ndbm می‌تواند هنگام به‌روزرسانی‌ها بدون هشدار پرونده پایگاه داده را خراب کند، که این می‌تواند هنگام تلاش برای خواندن از پایگاه داده باعث فروپاشی‌های سخت شود.

  • Shelf.reorganize() may not be available for all database packages and may temporarily increase resource usage (especially disk space) when called. Additionally, it will never run automatically and instead needs to be called explicitly.

class shelve.Shelf(dict, protocol=None, writeback=False, keyencoding='utf-8', *, serializer=None, deserializer=None)

زیرکلاسی از collections.abc.MutableMapping که مقادیر پیکل‌شده را در شیء dict ذخیره می‌کند.

به‌طور پیش‌فرض، از پیکل‌های ایجادشده با pickle.DEFAULT_PROTOCOL برای سریال‌سازی مقادیر استفاده می‌شود. نسخه‌ی پروتکل پیکل را می‌توان با پارامتر protocol مشخص کرد. برای بحثی درباره‌ی پروتکل‌های پیکل، مستندات pickle را ببینید.

اگر پارامتر writeback برابر True باشد، شیء نهانگاهی از تمام آیتم‌های دسترسی‌شده را نگه می‌دارد و آن‌ها را در زمان sync و close به دیکشنری بازمی‌نویسد. این امر عملیات طبیعی روی آیتم‌های تغییرپذیر را ممکن می‌سازد، اما می‌تواند حافظه بسیار بیشتری مصرف کند و باعث شود sync و close زمان زیادی طول بکشند.

پارامتر keyencoding کدگذاری‌ای است که برای کدگذاری کلیدها پیش از استفاده از آن‌ها در دیکشنری زیرین به کار می‌رود.

The serializer and deserializer parameters have the same interpretation as in open().

یک شیء Shelf همچنین می‌تواند به‌عنوان مدیر زمینه استفاده شود، که در این صورت با پایان یافتن بلوک with به‌طور خودکار بسته می‌شود.

تغییر یافته در نسخه‌ی 3.2: پارامتر keyencoding افزوده شد؛ پیش‌تر، کلیدها همیشه با UTF-8 کدگذاری می‌شدند.

تغییر یافته در نسخه‌ی 3.4: پشتیبانی از مدیر زمینه افزوده شد.

تغییر یافته در نسخه‌ی 3.10: pickle.DEFAULT_PROTOCOL اکنون به‌عنوان پروتکل پیش‌فرض pickle استفاده می‌شود.

تغییر یافته در نسخه‌ی 3.15: Added the serializer and deserializer parameters.

class shelve.BsdDbShelf(dict, protocol=None, writeback=False, keyencoding='utf-8', *, serializer=None, deserializer=None)

A subclass of Shelf which exposes first(), next(), previous(), last() and set_location() methods. These are available in the third-party bsddb module from pybsddb but not in other database modules. The dict object passed to the constructor must support those methods. This is generally accomplished by calling one of bsddb.hashopen(), bsddb.btopen() or bsddb.rnopen(). The optional protocol, writeback, keyencoding, serializer and deserializer parameters have the same interpretation as in open().

تغییر یافته در نسخه‌ی 3.15: Added the serializer and deserializer parameters.

class shelve.DbfilenameShelf(filename, flag='c', protocol=None, writeback=False, *, serializer=None, deserializer=None)

A subclass of Shelf which accepts a filename instead of a dict-like object. The underlying file will be opened using dbm.open(). By default, the file will be created and opened for both read and write. The optional flag parameter has the same interpretation as for the open() function. The optional protocol, writeback, serializer and deserializer parameters have the same interpretation as in open().

تغییر یافته در نسخه‌ی 3.15: Added the serializer and deserializer parameters.

مثال

برای جمع‌بندی رابط (key یک رشته است، data یک شیء دلخواه است):

import shelve

d = shelve.open(filename)  # open -- file may get suffix added by low-level
                           # library

d[key] = data              # store data at key (overwrites old data if
                           # using an existing key)
data = d[key]              # retrieve a COPY of data at key (raise KeyError
                           # if no such key)
del d[key]                 # delete data stored at key (raises KeyError
                           # if no such key)

flag = key in d            # true if the key exists
klist = list(d.keys())     # a list of all existing keys (slow!)

# as d was opened WITHOUT writeback=True, beware:
d['xx'] = [0, 1, 2]        # this works as expected, but...
d['xx'].append(3)          # *this doesn't!* -- d['xx'] is STILL [0, 1, 2]!

# having opened d without writeback=True, you need to code carefully:
temp = d['xx']             # extracts the copy
temp.append(5)             # mutates the copy
d['xx'] = temp             # stores the copy right back, to persist it

# or, d=shelve.open(filename,writeback=True) would let you just code
# d['xx'].append(5) and have it work as expected, BUT it would also
# consume more memory and make the d.close() operation slower.

d.close()                  # close it

Exceptions

exception shelve.ShelveError

Exception raised when one of the arguments deserializer and serializer is missing in the open(), Shelf, BsdDbShelf and DbfilenameShelf.

The deserializer and serializer arguments must be given together.

اضافه شده در نسخه‌ی 3.15.

همچنین ملاحظه نمائید

ماژول dbm

رابط عام برای پایگاه‌های داده به سبک dbm.

ماژول pickle

سریال‌سازی اشیاء که shelve از آن استفاده می‌کند.