Python

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()가 호출될 때 다시 기록됩니다; 이것은 영속 딕셔너리의 가변 항목을 변경하는 것을 더 수월하게 만들지만, 많은 항목이 액세스 되면, 캐시를 위해 막대한 양의 메모리를 소비할 수 있으며, 액세스 된 모든 항목을 다시 기록하기 때문에 닫기 연산이 매우 느려질 수 있습니다 (어떤 액세스 된 항목이 가변인지, 어떤 것이 실제로 변경되었는지를 판별할 방법이 없습니다).

기본적으로 shelve 는 직렬화 및 역직렬화에 pickle.dumps()pickle.loads() 를 사용합니다. 이는 각각 serializerdeserializer 를 제공하여 변경할 수 있습니다.

serializer 인자는 obj 객체와 protocol*을 입력받아 ``obj``의 표현을 :term:`bytes-like object`로 반환하는 호출 가능 객체여야 합니다. *protocol 값은 serializer에 의해 무시될 수 있습니다.

deserializer 인자는 bytes 객체로 주어진 직렬화된 객체를 입력받아 해당 객체를 반환하는 호출 가능 객체여야 합니다.

serializer 가 제공되지만 deserializer 가 제공되지 않거나 그 반대의 경우, ShelveError 가 발생합니다.

버전 3.10에서 변경: :const:`pickle.DEFAULT_PROTOCOL`이 이제 기본 피클 프로토콜로 사용됩니다.

버전 3.11에서 변경: filename 매개 변수는 :term:`path-like object`를 받습니다.

버전 3.15에서 변경: pickle.dumps`와 :func:`pickle.loads() 대신 사용자 정의 serializerdeserializer 함수를 받습니다.

참고

쉘프가 자동으로 닫히는 것에 의지하지 마십시오; 더는 필요 없을 때 close()를 명시적으로 호출하거나, shelve.open()을 컨텍스트 관리자로 사용하십시오:

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

경고

shelve 모듈은 :mod:`pickle`에 의해 뒷받침되므로, 신뢰할 수 없는 소스에서 쉘프를 로드하는 것은 안전하지 않습니다. pickle과 마찬가지로, 쉘프를 로드하면 임의의 코드를 실행할 수 있습니다.

쉘프 객체는 딕셔너리가 지원하는 대부분의 메서드와 연산을 지원합니다 (복사, 생성자 및 연산자 |``와 ``|= 제외). 이는 딕셔너리 기반 스크립트에서 지속적 저장을 요구하는 스크립트로의 전환을 용이하게 합니다.

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

Shelf.sync()

쉘프를 writebackTrue 로 설정하여 열었으면, 캐시의 모든 항목을 기록합니다. 또한, 가능하다면 캐시를 비우고 디스크 상의 영속 딕셔너리를 동기화합니다. 이는 reorganize() 가 호출되거나 쉘프가 close() 로 닫힐 때 자동으로 호출됩니다.

Shelf.reorganize()

:meth:`sync`를 호출하고 삭제로 인해 발생한 빈 공간을 제거하여 디스크 사용 공간을 줄입니다.

Added in version 3.15.

Shelf.close()

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

더 보기

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

제약 사항

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

  • shelve 모듈은 쉘브된 객체에 대한 동시성(concurrent) 읽기/쓰기 액세스를 지원하지 않습니다. (여러 동시적인 읽기 액세스는 안전합니다.) 프로그램이 쓰기 용으로 쉘프를 열고 있으면, 다른 프로그램은 읽기나 쓰기 용으로 열지 않아야 합니다. 유닉스 파일 잠금으로 해결할 수 있지만, 이는 유닉스 버전에 따라 다르며 사용된 데이터베이스 구현에 대한 지식이 필요합니다.

  • macOS에서 :mod:`dbm.ndbm`은 업데이트 시 데이터베이스 파일을 조용히 손상시킬 수 있으며, 이로 인해 데이터베이스에서 읽으려고 할 때 심각한 충돌이 발생할 수 있습니다.

  • :meth:`Shelf.reorganize`가 모든 데이터베이스 패키지에서 사용 가능하지 않을 수 있으며 호출 시 리소스 사용량(특히 디스크 공간)을 일시적으로 증가시킬 수 있습니다. 또한, 자동으로 실행되지 않으며 명시적으로 호출해야 합니다.

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에 사용되기 전에 키를 인코딩하는 데 사용되는 인코딩입니다.

serializerdeserializer 매개 변수는 :func:`~shelve.open`에서와 동일한 해석을 가집니다.

Shelf 객체는 컨텍스트 관리자로 사용할 수도 있습니다. 이 경우 with 블록이 끝날 때 자동으로 닫힙니다.

버전 3.2에서 변경: keyencoding 매개 변수가 추가되었습니다; 이전에는 키가 항상 UTF-8으로 인코딩되었습니다.

버전 3.4에서 변경: 컨텍스트 관리자 지원 추가.

버전 3.10에서 변경: :const:`pickle.DEFAULT_PROTOCOL`이 이제 기본 피클 프로토콜로 사용됩니다.

버전 3.15에서 변경: serializerdeserializer 매개 변수를 추가했습니다.

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

Shelf`의 서브 클래스로, :meth:!first`, next(), previous(), last(), 및 set_location() 메서드를 노출합니다. 이는 제삼자 bsddb 모듈(from pybsddb <https://www.jcea.es/programacion/pybsddb.htm>`_에서 제공)에서 사용할 수 있지만 다른 데이터베이스 모듈에서는 사용할 수 없습니다. 생성자에 전달되는 *dict* 객체는 해당 메서드를 지원해야 합니다. 이는 일반적으로 :func:!bsddb.hashopen`, bsddb.btopen() 또는 bsddb.rnopen() 중 하나를 호출하여 수행됩니다. 선택적 protocol, writeback, keyencoding, serializer, deserializer 매개 변수는 :func:`~shelve.open`에서와 동일한 해석을 가집니다.

버전 3.15에서 변경: serializerdeserializer 매개 변수를 추가했습니다.

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

딕셔너리 같은 객체 대신 filename\을 받아들이는 Shelf\의 서브 클래스입니다. 하부 파일은 dbm.open()\을 사용하여 열립니다. 기본적으로, 파일은 읽기와 쓰기가 가능하도록 생성되고 열립니다. 선택적 flag 매개 변수는 open() 함수와 동일하게 해석됩니다. 선택적 protocol, writeback, serializerdeserializer 매개 변수는 :func:`~shelve.open`에서와 동일하게 해석됩니다.

버전 3.15에서 변경: serializerdeserializer 매개 변수를 추가했습니다.

예제

인터페이스를 요약하면 (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()                  # 닫습니다

예외

exception shelve.ShelveError

인자 deserializerserializer 중 하나가 open(), Shelf, BsdDbShelf 및 :class:`DbfilenameShelf`에서 누락될 때 발생하는 예외입니다.

deserializerserializer 인자는 함께 제공되어야 합니다.

Added in version 3.15.

더 보기

모듈 dbm

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

모듈 pickle

shelve\에 의해 사용되는 객체 직렬화.

분실물 보관소