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 를 제공하여 변경할 수 있습니다.

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.

deserializer 인자는 bytes 객체로 제공된 직렬화된 객체를 입력으로 받아 대응하는 객체를 반환하는 호출 가능(callable) 객체여야 합니다.

serializer 는 제공되었으나 deserializer 가 없거나, 그 반대의 경우에 ShelveError 가 발생합니다.

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

버전 3.11에서 변경: 파일명으로 경로류 객체 를 수락합니다.

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

참고

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

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

경고

shelve 모듈은 pickle 을 기반으로 하므로 신뢰할 수 없는 소스에서 쉘프를 로드하는 것은 안전하지 않습니다. 피클과 마찬가지로, 쉘프를 로드하면 임의의 코드가 실행될 수 있습니다.

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

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

Shelf.sync()

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

Shelf.reorganize()

sync() 를 호출하고 삭제로 인해 발생한 빈 공간을 제거하여 디스크 사용량을 줄이려고 시도합니다.

Added in version 3.15.

Shelf.close()

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

더 보기

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

제약 사항

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

  • shelve 모듈은 쉘프된 객체에 대한 동시(concurrent) 읽기/쓰기 액세스를 지원하지 않습니다. (여러 개의 동시 읽기 접근은 안전합니다.) 어떤 프로그램이 쓰기용으로 쉘프를 열고 있는 동안, 다른 어떤 프로그램도 이를 읽거나 쓰기 위해 열어서는 안 됩니다. 유닉스 파일 잠금을 사용하여 이 문제를 해결할 수 있지만, 이는 유닉스 버전마다 다르며 사용된 데이터베이스 구현에 대한 지식이 필요합니다.

  • macOS에서 dbm.ndbm 은 업데이트 시 데이터베이스 파일을 조용히 손상시킬 수 있으며, 이는 데이터베이스를 읽으려 할 때 시스템이 중단되는 현상을 일으킬 수 있습니다.

  • 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 매개 변수는 open() 과 동일하게 해석됩니다.

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

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

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

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

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

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

first(), next(), previous(), last()set_location() 메서드를 노출하는 Shelf 의 서브 클래스입니다. 이 메서드들은 pybsddb 의 제3자 bsddb 모듈에서 사용할 수 있지만 다른 데이터베이스 모듈에서는 사용할 수 없습니다. 생성자에 전달되는 dict 객체는 해당 메서드들을 지원해야 합니다. 이는 일반적으로 bsddb.hashopen(), bsddb.btopen() 또는 bsddb.rnopen() 중 하나를 호출하여 수행됩니다. 선택적 protocol, writeback, keyencoding, serializerdeserializer 매개 변수는 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 매개 변수는 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

open(), Shelf, BsdDbShelfDbfilenameShelf 에서 deserializer 또는 serializer 중 하나가 누락된 경우 발생하는 예외입니다.

deserializer*와 *serializer 인자는 함께 제공되어야 합니다.

Added in version 3.15.

더 보기

모듈 dbm

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

모듈 pickle

shelve 에서 사용되는 객체 직렬화.

분실물 보관소