# `shelve` — Python object persistence

Вихідний код: Lib/shelve.py

«Полиця» — це постійний об’єкт, схожий на словник. Різниця з базами даних «dbm» полягає в тому, що значення (не ключі!) на полиці можуть бути по суті довільними об’єктами Python — будь-чим, що може обробити модуль `pickle`. Це включає більшість екземплярів класів, рекурсивних типів даних та об’єктів, що містять багато спільних підоб’єктів. Ключі - звичайні струни.

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

  Відкрийте постійний словник. Вказана назва файлу є базовою назвою файлу базової бази даних. Як побічний ефект до назви файлу може бути додано розширення та може бути створено більше одного файлу. За замовчуванням базовий файл бази даних відкрито для читання та запису. Необов’язковий параметр flag має таку саму інтерпретацію, що й параметр flag `dbm.open()`.

  By default, pickles created with `pickle.DEFAULT_PROTOCOL` are used to serialize values. The version of the pickle protocol can be specified with the protocol parameter.

  Через семантику Python полиця не може знати, коли змінено запис постійного словника. За замовчуванням змінені об’єкти записуються тільки, коли вони призначені на полицю (див. приклад). Якщо необов’язковий параметр writeback має значення `True`, усі записи, до яких здійснюється доступ, також кешуються в пам’яті та записуються назад у `sync()` і `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 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` is now used as the default pickle protocol.

  Змінено в версії 3.11: Accepts path-like object for filename.

  Змінено в версії 3.15.0a0 (unreleased): Accepts custom serializer and deserializer functions in place of `pickle.dumps()` and `pickle.loads()`.

  Примітка

  Не покладайтеся на автоматичне закриття полиці; завжди викликайте `close()` явно, коли він вам більше не потрібен, або використовуйте `shelve.open()` як контекстний менеджер:

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

Попередження

Оскільки модуль `shelve` підтримується `pickle`, небезпечно завантажувати полицю з ненадійного джерела. Як і з pickle, завантаження полиці може виконувати довільний код.

Об’єкти полиці підтримують більшість методів і операцій, які підтримуються словниками (крім копіювання, конструкторів і операторів `|` і `|=`). Це спрощує перехід від сценаріїв на основі словників до сценаріїв, які потребують постійного зберігання.

Підтримуються два додаткові методи:

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.

  Added in version 3.15.0a0 (unreleased).

Shelf.close()

  Синхронізуйте та закрийте постійний об’єкт dict. Операції на закритій полиці завершаться помилкою з `ValueError`.

Дивись також

Persistent dictionary recipe with widely supported storage formats and having the speed of native dictionaries.

## Обмеження

- Вибір того, який пакет бази даних використовуватиметься (наприклад, `dbm.ndbm` або `dbm.gnu`) залежить від доступного інтерфейсу. Тому небезпечно відкривати базу даних безпосередньо за допомогою `dbm`. База даних також (на жаль) підлягає обмеженням `dbm`, якщо вона використовується — це означає, що (вибране представлення) об’єктів, які зберігаються в базі даних, мають бути досить малими, і в окремих випадках колізії ключів можуть призвести до відмови бази даних в оновленнях.

- Модуль `shelve` не підтримує одночасний доступ для читання/запису до відкладених об’єктів. (Кілька одночасних доступів для читання є безпечними.) Якщо в програмі є полиця, відкрита для запису, жодна інша програма не повинна мати її відкритою для читання чи запису. Щоб вирішити цю проблему, можна використовувати блокування файлів Unix, але це відрізняється в різних версіях Unix і вимагає знання про використовувану реалізацію бази даних.

- On macOS `dbm.ndbm` can silently corrupt the database file on updates, which can cause hard crashes when trying to read from the database.

- `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.

  By default, pickles created with `pickle.DEFAULT_PROTOCOL` are used to serialize values. The version of the pickle protocol can be specified with the protocol parameter. See the `pickle` documentation for a discussion of the pickle protocols.

  Якщо параметр writeback має значення `True`, об’єкт зберігатиме кеш усіх записів, до яких отримав доступ, і записуватиме їх назад у dict під час синхронізації та закриття. Це дозволяє виконувати природні операції над змінними записами, але може споживати набагато більше пам’яті, а синхронізація та закриття триватимуть довго.

  Параметр keyencoding — це кодування, яке використовується для кодування ключів перед їх використанням із базовим dict.

  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` is now used as the default pickle protocol.

  Змінено в версії 3.15.0a0 (unreleased): 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.0a0 (unreleased): 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.0a0 (unreleased): 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.

  Added in version 3.15.0a0 (unreleased).

Дивись також

Модуль `dbm`

  Загальний інтерфейс до баз даних у стилі `dbm`.

Модуль `pickle`

  Серіалізація об’єктів, яку використовує `shelve`.