shelve — Python 객체 지속성

shelve — Python 객체 지속성

"shelf"는 지속적인 사전과 유사한 객체입니다. "dbm" 데이터베이스와의 차이점은 shelf의 값(키가 아니라!)이 본질적으로 임의의 Python 객체일 수 있다는 것입니다 — pickle 모듈이 처리할 수 있는 무엇이든 말입니다. 여기에는 대부분의 클래스 인스턴스, 재귀 데이터 타입, 많은 공유 하위 객체를 포함하는 객체가 포함됩니다. 키는 일반적인 문자열입니다.

출처: Python documentation

본문

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

지속적인 사전을 엽니다. 지정된 filename은 기저 데이터베이스의 기본 파일 이름입니다. 부작용으로 확장자가 파일 이름에 추가되고 둘 이상의 파일이 생성될 수 있습니다. 기본적으로 기저 데이터베이스 파일은 읽기와 쓰기용으로 열립니다. 선택적 flag 매개변수는 dbm.open()flag 매개변수와 같은 해석을 가집니다.

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

Python 의미론 때문에 shelf는 가변 지속 사전 항목이 언제 수정되는지 알 수 없습니다. 기본적으로 수정된 객체는 shelf에 할당될 때만 기록됩니다(예제 참고). 선택적 writeback 매개변수가 True로 설정되면 접근한 모든 항목도 메모리에 캐시되고 sync()close()에서 다시 기록됩니다. 이것은 지속 사전의 가변 항목을 변경하는 것을 더 편리하게 만들 수 있지만, 많은 항목에 접근하면 캐시에 방대한 메모리를 소비할 수 있고, 접근한 모든 항목이 다시 기록되므로(어떤 접근 항목이 가변인지, 어떤 것이 실제로 변경되었는지 결정할 방법이 없으므로) close 작업을 매우 느리게 만들 수 있습니다.

versionchanged: 3.10에서 pickle.DEFAULT_PROTOCOL이 이제 기본 pickle 프로토콜로 사용됩니다.

versionchanged: 3.11에서 filename에 path-like 객체를 받습니다.

Note

shelf가 자동으로 닫히는 것에 의존하지 마세요. 더 이상 필요하지 않을 때 항상 close()를 명시적으로 호출하거나 shelve.open()을 컨텍스트 관리자로 사용하세요:

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

Warning

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

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

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

  • Shelf.sync() — shelf가 writebackTrue로 설정하여 열렸으면 캐시의 모든 항목을 다시 기록합니다. 또한 가능하면 캐시를 비우고 지속 사전을 디스크에 동기화합니다. shelf가 close()로 닫힐 때 자동으로 호출됩니다.
  • Shelf.close() — 지속 dict 객체를 동기화하고 닫습니다. 닫힌 shelf에 대한 연산은 ValueError로 실패합니다.

See also

널리 지원되는 저장 형식을 가지면서 네이티브 사전의 속도를 가진 지속 사전 레시피(Persistent dictionary recipe).

제한 사항

  • 어떤 데이터베이스 패키지(dbm.ndbm 또는 dbm.gnu 같은)가 사용될지는 어떤 인터페이스를 사용할 수 있는지에 따라 달라집니다. 따라서 dbm을 사용하여 데이터베이스를 직접 여는 것은 안전하지 않습니다. 또한 (불행하게도) 데이터베이스는 dbm을 사용하면 그 제한의 대상이 됩니다 — 즉 데이터베이스에 저장된 객체의 (pickle된 표현)은 꽤 작아야 하고, 드물게 키 충돌이 데이터베이스가 업데이트를 거부하게 만들 수 있습니다.
  • shelve 모듈은 shelved 객체에 대한 동시 읽기/쓰기 접근을 지원하지 않습니다. (여러 동시 읽기 접근은 안전합니다.) 프로그램이 쓰기 위해 shelf를 열면 다른 프로그램은 읽기나 쓰기로 열어서는 안 됩니다. Unix 파일 잠금을 사용하여 이 문제를 해결할 수 있지만 이것은 Unix 버전마다 다르고 사용된 데이터베이스 구현에 대한 지식이 필요합니다.
  • macOS에서 dbm.ndbm은 업데이트 시 데이터베이스 파일을 조용히 손상시킬 수 있으며, 데이터베이스에서 읽으려고 할 때 심각한 충돌을 유발할 수 있습니다.

shelve.Shelf(dict, protocol=None, writeback=False, keyencoding='utf-8')

pickle된 값을 dict 객체에 저장하는 collections.abc.MutableMapping의 하위 클래스.

기본적으로 pickle.DEFAULT_PROTOCOL로 생성된 pickle이 값을 직렬화하는 데 사용됩니다. pickle 프로토콜의 버전은 protocol 매개변수로 지정할 수 있습니다. pickle 프로토콜에 대한 논의는 pickle 문서를 참고하세요.

writeback 매개변수가 True이면 객체는 접근한 모든 항목의 캐시를 보유하고 sync 및 close 시간에 그들을 dict에 다시 기록합니다. 이것은 가변 항목에 대한 자연스러운 연산을 허용하지만 훨씬 더 많은 메모리를 소비하고 sync와 close가 오래 걸리게 만들 수 있습니다.

keyencoding 매개변수는 키가 기저 dict와 함께 사용되기 전에 인코딩하는 데 사용되는 인코딩입니다.

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

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

versionchanged: 3.4에서 컨텍스트 관리자 지원이 추가되었습니다.

versionchanged: 3.10에서 pickle.DEFAULT_PROTOCOL이 이제 기본 pickle 프로토콜로 사용됩니다.

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

first(), next(), previous(), last(), set_location() 메서드를 노출하는 Shelf의 하위 클래스. 이것들은 pybsdb의 서드파티 bsddb 모듈에서 사용할 수 있지만 다른 데이터베이스 모듈에서는 사용할 수 없습니다. 생성자에 전달된 dict 객체는 그 메서드들을 지원해야 합니다. 이것은 일반적으로 bsddb.hashopen(), bsddb.btopen() 또는 bsddb.rnopen() 중 하나를 호출하여 달성됩니다. 선택적 protocol, writeback, keyencoding 매개변수는 Shelf 클래스와 같은 해석을 가집니다.

shelve.DbfilenameShelf(filename, flag='c', protocol=None, writeback=False)

dict-like 객체 대신 파일 이름을 받는 Shelf의 하위 클래스. 기저 파일은 dbm.open()을 사용하여 열립니다. 기본적으로 파일은 읽기와 쓰기 모두로 생성되고 열립니다. 선택적 flag 매개변수는 open() 함수와 같은 해석을 가집니다. 선택적 protocolwriteback 매개변수는 Shelf 클래스와 같은 해석을 가집니다.

예제

인터페이스를 요약하면(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

See also

  • Module dbm — dbm 스타일 데이터베이스에 대한 일반 인터페이스.
  • Module pickle — shelve가 사용하는 객체 직렬화.

더 알아보기 (Learn more)