"shelve" --- 파이썬 객체 지속성
*******************************

**소스 코드:** Lib/shelve.py

======================================================================

"쉘프(shelf)"는 영속적인(persistent) 딕셔너리류 객체입니다. "dbm" 데이
터베이스와의 차이점은 쉘프의 값(키가 아닙니다!)이 사실상 임의의 파이썬
객체일 수 있다는 것입니다 --- "pickle" 모듈에서 처리할 수 있는 모든 것
입니다. 여기에는 대부분의 클래스 인스턴스, 재귀적 데이터형 및 많은 공
유 서브 객체를 포함하는 객체가 포함됩니다. 키는 일반 문자열입니다.

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

   영속적 딕셔너리를 엽니다. 지정된 filename은 하부 데이터베이스의 기
   본 파일명입니다. 부작용으로, 확장명이 파일명에 추가될 수 있으며 여
   러 개의 파일이 만들어질 수 있습니다. 기본적으로, 하부 데이터베이스
   파일은 읽기와 쓰기 용으로 열립니다. 선택적 *flag* 매개 변수는
   "dbm.open()"의 *flag* 매개 변수와 같게 해석됩니다.

   기본적으로, 값을 직렬화하는 데 "pickle.DEFAULT_PROTOCOL"로 생성된
   피클이 사용됩니다. 피클 프로토콜의 버전은 *protocol* 매개 변수로 지
   정할 수 있습니다.

   파이썬 의미론 때문에, 쉘프는 가변 영속 딕셔너리 항목이 언제 수정되
   는지 알 수 없습니다. 기본적으로 수정된 객체는 쉘프에 *대입될 때만*
   기록됩니다 (예제를 참조하십시오). 선택적인 *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 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" is now used as the
   default pickle protocol.

   버전 3.11에서 변경: Accepts *path-like object* for filename.

   버전 3.15에서 변경: 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'

경고:

  Because the "shelve" module is backed by "pickle", it is insecure to
  load a shelf from an untrusted source.  Like with pickle, loading a
  shelf can execute arbitrary code.

Shelf objects support most of the methods and operations supported by
dictionaries (except copying, constructors and operators "|" and
"|=").  This eases the transition from dictionary based scripts to
those requiring persistent storage.

두 가지 추가 메서드가 지원됩니다:

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.

Shelf.close()

   영구 *딕셔너리* 객체를 동기화하고 닫습니다. 닫힌 쉘프에 대한 연산은
   "ValueError"로 실패합니다.

더 보기: 널리 지원되는 저장 형식과 기본 딕셔너리의 속도를 갖춘 Persistent
      dictionary recipe


제약 사항
=========

* 사용되는 데이터베이스 패키지의 선택(가령 "dbm.ndbm"이나 "dbm.gnu")은
  어떤 인터페이스가 사용 가능한지에 따라 다릅니다. 따라서 "dbm"을 사용
  하여 데이터베이스를 직접 여는 것은 안전하지 않습니다. 또한, 데이터베
  이스는 (불행히도) "dbm"이 사용된다면 그것의 제약이 적용됩니다 --- 이
  것은 데이터베이스에 저장되는 객체(의 피클 된 표현이)가 상당히 작아야
  하며, 드물긴 하지만 키 충돌로 인해 데이터베이스가 업데이트를 거부할
  수 있음을 뜻합니다.

* The "shelve" module does not support *concurrent* read/write access
  to shelved objects.  (Multiple simultaneous read accesses are safe.)
  When a program has a shelf open for writing, no other program should
  have it open for reading or writing.  Unix file locking can be used
  to solve this, but this differs across Unix versions and requires
  knowledge about the database implementation used.

* 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)

   *dict* 객체에 피클 된 값을 저장하는
   "collections.abc.MutableMapping"의 서브 클래스.

   기본적으로, 값을 직렬화하는 데 "pickle.DEFAULT_PROTOCOL"로 생성된
   피클이 사용됩니다. 피클 프로토콜의 버전은 *protocol* 매개 변수로 지
   정할 수 있습니다. 피클 프로토콜에 대한 설명은 "pickle" 설명서를 참
   조하십시오.

   *writeback* 매개 변수가 "True"이면, 객체는 액세스 된 모든 항목의 캐
   시를 보유하고 sync와 close 할 때 *dict*에 다시 씁니다. 이것은 가변
   항목에 대한 자연스러운 연산을 허락하지만, 더 많은 메모리를 소비하고
   sync와 close 연산이 오래 걸릴 수 있습니다.

   *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에서 변경: 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)  # 열기 -- 파일은 저수준 라이브러리에 의해 추가된 접미사를 얻을
                              # 수 있습니다

   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 없이 열린 d에서는, 신중하게 코딩해야 합니다:
   temp = d['xx']             # 사본을 꺼냅니다
   temp.append(5)             # 사본을 수정합니다
   d['xx'] = temp             # 영속적으로 만들기 위해, 사본을 다시 저장합니다

   # 또는, d=shelve.open(filename,writeback=True)는 단지 d['xx'].append(5)로
   # 코딩해도 기대한 대로 동작하게 만들지만, 더 많은 메모리를 소비하고 d.close() 연산을 더
   # 느리게 만듭니다.

   d.close()                  # 닫습니다


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.

더 보기:

  모듈 "dbm"
     "dbm" 스타일 데이터베이스에 대한 범용 인터페이스.

  모듈 "pickle"
     Object serialization used by "shelve".
