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,
shelveusespickle.dumps()andpickle.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
objand the protocol as inputs and returns the representationobjas 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
bytesobject and returns the corresponding object.A
ShelveErroris 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()andpickle.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 whenreorganize()is called or the shelf is closed withclose().
- 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
Shelfwhich exposesfirst(),next(),previous(),last()andset_location()methods. These are available in the third-partybsddbmodule 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 ofbsddb.hashopen(),bsddb.btopen()orbsddb.rnopen(). The optional protocol, writeback, keyencoding, serializer and deserializer parameters have the same interpretation as inopen().تغییر یافته در نسخهی 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
Shelfwhich accepts a filename instead of a dict-like object. The underlying file will be opened usingdbm.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 theopen()function. The optional protocol, writeback, serializer and deserializer parameters have the same interpretation as inopen().تغییر یافته در نسخهی 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,BsdDbShelfandDbfilenameShelf.The deserializer and serializer arguments must be given together.
اضافه شده در نسخهی 3.15.