다음과 같은 객체를 만들었습니다.
company1.name = 'banana'
company1.value = 40
이 개체를 저장하고 싶습니다. 어떻게해야합니까?
답변
pickle
표준 라이브러리에서 모듈을 사용할 수 있습니다 . 다음은 예제에 기본 응용 프로그램입니다.
import pickle
class Company(object):
def __init__(self, name, value):
self.name = name
self.value = value
with open('company_data.pkl', 'wb') as output:
company1 = Company('banana', 40)
pickle.dump(company1, output, pickle.HIGHEST_PROTOCOL)
company2 = Company('spam', 42)
pickle.dump(company2, output, pickle.HIGHEST_PROTOCOL)
del company1
del company2
with open('company_data.pkl', 'rb') as input:
company1 = pickle.load(input)
print(company1.name) # -> banana
print(company1.value) # -> 40
company2 = pickle.load(input)
print(company2.name) # -> spam
print(company2.value) # -> 42
파일을 열고 단일 객체를 작성하는 다음과 같은 간단한 유틸리티를 정의 할 수도 있습니다.
def save_object(obj, filename):
with open(filename, 'wb') as output: # Overwrites any existing file.
pickle.dump(obj, output, pickle.HIGHEST_PROTOCOL)
# sample usage
save_object(company1, 'company1.pkl')
최신 정보
이것은 인기있는 답변이므로 몇 가지 고급 사용법 주제를 터치하고 싶습니다.
cPickle
(또는 _pickle
) vspickle
전자는 C로 작성되고 훨씬 빠르기 때문에 실제로 cPickle
모듈을 사용하는 것이 거의 항상 바람직합니다 pickle
. 그들 사이에는 약간의 차이가 있지만 대부분의 상황에서 동등하며 C 버전은 훨씬 우수한 성능을 제공합니다. 그것을 쉽게 전환 할 수는 없었습니다 import
.
import cPickle as pickle
Python 3에서는 cPickle
이름이 바뀌 _pickle
었지만 pickle
이제 모듈이 자동으로 수행 되므로 더 이상 필요하지 않습니다 . Python 3에서 pickle과 _pickle의 차이점 은 무엇입니까?를 참조하십시오 . .
요약은 코드가 Python 2와 3에서 모두 사용 가능한 경우 코드가 항상 C 버전을 사용 하도록하기 위해 다음과 같은 것을 사용할 수 있다는 것입니다 .
try:
import cPickle as pickle
except ModuleNotFoundError:
import pickle
데이터 스트림 형식 (프로토콜)
pickle
“프로토콜 버전 0″은 ASCII이므로 “사람이 읽을 수있는” 문서에 설명 된대로 프로토콜 이라고하는 여러 가지 파이썬 고유의 형식으로 파일을 읽고 쓸 수 있습니다 . 0보다 큰 버전은 바이너리이며 사용 가능한 가장 높은 버전은 사용중인 Python 버전에 따라 다릅니다. 기본값은 Python 버전에 따라 다릅니다. Python 2에서 기본값은 Protocol version 이지만 Python 3.8.1에서는 Protocol version 입니다. Python 3.x에서 모듈에 추가되었지만 Python 2에는 존재하지 않습니다.0
4
pickle.DEFAULT_PROTOCOL
운 좋게도 pickle.HIGHEST_PROTOCOL
모든 호출에서 쓰는 것은 축약 형입니다 (원하는 것으로 가정하고 일반적으로 수행한다고 가정) -1
. 음수 인덱스를 통해 시퀀스의 마지막 요소를 참조하는 것과 비슷한 리터럴 숫자 만 사용하십시오 . 따라서 글을 쓰는 대신 :
pickle.dump(obj, output, pickle.HIGHEST_PROTOCOL)
당신은 쓸 수 있습니다 :
pickle.dump(obj, output, -1)
어느 쪽이든, Pickler
다중 피클 작업에 사용할 객체를 만든 경우 프로토콜을 한 번만 지정했을 것입니다 .
pickler = pickle.Pickler(output, -1)
pickler.dump(obj1)
pickler.dump(obj2)
etc...
참고 : 다른 버전의 Python을 실행하는 환경에서 모든 프로토콜이 읽을 수있는 특정 프로토콜 번호를 명시 적으로 사용 (하드 코드)하고 싶을 것입니다 (나중 버전은 일반적으로 이전 버전에서 생성 된 파일을 읽을 수 있음) .
여러 객체
피클 파일이있는 동안 수 중 알 수없는 번호가있을 때, 위의 샘플과 같이 절인 객체의 수를 포함, 그것은 가변 크기의 컨테이너 일종의 그들 모두를 저장하는 유사한하는 것이 쉽게 list
, tuple
또는 dict
및 쓰기 한 번의 호출로 파일에 모두 :
tech_companies = [
Company('Apple', 114.18), Company('Google', 908.60), Company('Microsoft', 69.18)
]
save_object(tech_companies, 'tech_companies.pkl')
다음을 사용하여 목록과 목록의 모든 내용을 복원하십시오.
with open('tech_companies.pkl', 'rb') as input:
tech_companies = pickle.load(input)
가장 큰 장점은 나중에 다시로드하기 위해 얼마나 많은 객체 인스턴스가 저장되어 있는지 알 필요가 없다는 것입니다 (정보 가 없으면 가능하지만 약간 특수화 된 코드가 필요합니다). 관련 질문에 대한 답변보기 피클 파일로 여러 객체 저장 및로드? 다양한 방법에 대한 자세한 내용은 개인적으로 나는 @Lutz Prechelt의 답변 이 가장 좋습니다. 여기 예제에 맞게 조정되었습니다.
class Company:
def __init__(self, name, value):
self.name = name
self.value = value
def pickled_items(filename):
""" Unpickle a file of pickled data. """
with open(filename, "rb") as f:
while True:
try:
yield pickle.load(f)
except EOFError:
break
print('Companies in pickle file:')
for company in pickled_items('company_data.pkl'):
print(' name: {}, value: {}'.format(company.name, company.value))
답변
객체가이라고 가정하는 것은 매우 강력한 가정이라고 생각합니다 class
. 그렇지 않은 경우 어떻게해야 class
합니까? 인터프리터에서 객체가 정의되지 않았다는 가정도 있습니다. 인터프리터에 정의되어 있으면 어떻게됩니까? 또한 속성이 동적으로 추가 된 경우 어떻게해야합니까? 일부 파이썬 객체가 __dict__
생성 후 속성이 추가되면 해당 속성의 추가를 pickle
존중하지 않습니다 (즉 pickle
, 객체 정의에 대한 참조로 직렬화 되기 때문에 속성이 추가 된 것을 잊어 버립니다 ).
이러한 모든 경우에, pickle
그리고 cPickle
끔찍하게 당신을 실패 할 수 있습니다.
object
속성 (객체 정의에 추가되거나 나중에 추가됨)이있는 곳 (임의로 생성 됨) 을 저장하려는 경우 가장 좋은 방법은을 사용 dill
하는 것입니다. 파이썬에서 거의 모든 것을 직렬화 할 수 있습니다.
우리는 수업으로 시작합니다…
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pickle
>>> class Company:
... pass
...
>>> company1 = Company()
>>> company1.name = 'banana'
>>> company1.value = 40
>>> with open('company.pkl', 'wb') as f:
... pickle.dump(company1, f, pickle.HIGHEST_PROTOCOL)
...
>>>
이제 종료하고 다시 시작하십시오 …
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pickle
>>> with open('company.pkl', 'rb') as f:
... company1 = pickle.load(f)
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1378, in load
return Unpickler(file).load()
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 858, in load
dispatch[key](self)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1090, in load_global
klass = self.find_class(module, name)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1126, in find_class
klass = getattr(mod, name)
AttributeError: 'module' object has no attribute 'Company'
>>>
죄송합니다… pickle
처리 할 수 없습니다. 시도합시다 dill
. 다른 객체 유형 (lambda
좋은 측정을 위해 )을 것입니다.
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> class Company:
... pass
...
>>> company1 = Company()
>>> company1.name = 'banana'
>>> company1.value = 40
>>>
>>> company2 = lambda x:x
>>> company2.name = 'rhubarb'
>>> company2.value = 42
>>>
>>> with open('company_dill.pkl', 'wb') as f:
... dill.dump(company1, f)
... dill.dump(company2, f)
...
>>>
이제 파일을 읽습니다.
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> with open('company_dill.pkl', 'rb') as f:
... company1 = dill.load(f)
... company2 = dill.load(f)
...
>>> company1
<__main__.Company instance at 0x107909128>
>>> company1.name
'banana'
>>> company1.value
40
>>> company2.name
'rhubarb'
>>> company2.value
42
>>>
효과가있다. 그 이유는 pickle
실패하고 dill
그렇지 않은 이유 는 (대부분) 모듈처럼 dill
취급 __main__
하고 참조로 피클 링하는 대신 클래스 정의를 피클 할 수 있기 때문입니다 (예 :pickle
입니다. dill
a를 피클 링 할 수 있는 이유 lambda
는 그것이 이름을 부여하기 때문입니다. 그러면 피클 링 매직이 일어날 수 있습니다.
실제로, 특히 만든 많은 개체가있는 경우 이러한 모든 개체를 저장하는 더 쉬운 방법이 있습니다. 전체 파이썬 세션을 덤프하고 나중에 다시 방문하십시오.
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> class Company:
... pass
...
>>> company1 = Company()
>>> company1.name = 'banana'
>>> company1.value = 40
>>>
>>> company2 = lambda x:x
>>> company2.name = 'rhubarb'
>>> company2.value = 42
>>>
>>> dill.dump_session('dill.pkl')
>>>
이제 컴퓨터를 끄고 에스프레소 등을 즐기고 나중에 다시 오십시오 …
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> dill.load_session('dill.pkl')
>>> company1.name
'banana'
>>> company1.value
40
>>> company2.name
'rhubarb'
>>> company2.value
42
>>> company2
<function <lambda> at 0x1065f2938>
유일한 주요 단점은 dill
파이썬 표준 라이브러리의 일부가 아니라는 것입니다. 따라서 서버에 파이썬 패키지를 설치할 수 없으면 사용할 수 없습니다.
그러나 시스템에 파이썬 패키지를 설치할 수 있다면로 최신 버전 dill
을 구할 수 있습니다 git+https://github.com/uqfoundation/dill.git@master#egg=dill
. 로 최신 릴리스 버전을 얻을 수 있습니다 pip install dill
.
답변
anycache 를 사용 하여 작업을 수행 할 수 있습니다 . 모든 세부 사항을 고려합니다.
- 딜 을 백엔드로 사용 하여 파이썬
pickle
모듈을 확장하여lambda
모든 멋진 파이썬 기능 을 처리 합니다. - 다른 객체를 다른 파일에 저장하고 올바르게 다시로드합니다.
- 캐시 크기를 제한합니다
- 캐시 지우기 허용
- 여러 실행간에 객체를 공유 할 수 있습니다
- 결과에 영향을 미치는 입력 파일을 존중할 수 있습니다
myfunc
인스턴스를 생성 하는 함수가 있다고 가정합니다 .
from anycache import anycache
class Company(object):
def __init__(self, name, value):
self.name = name
self.value = value
@anycache(cachedir='/path/to/your/cache')
def myfunc(name, value)
return Company(name, value)
Anycache myfunc
는 처음에 호출 하고 파일 cachedir
이름으로 함수 이름 및 인수에 따라 고유 식별자 를 사용하여 결과를 파일로 피클합니다 . 연속 실행시 절인 개체가로드됩니다. 이 경우 cachedir
파이썬 실행 사이의 보존, 절임 객체는 이전 파이썬 실행에서 가져옵니다.
자세한 내용은 설명서를 참조하십시오
답변
company1
python3과 함께 귀하의 질문에서 사용 하는 빠른 예 .
import pickle
# Save the file
pickle.dump(company1, file = open("company1.pickle", "wb"))
# Reload the file
company1_reloaded = pickle.load(open("company1.pickle", "rb"))
그러나이 답변에서 지적했듯이 피클은 종종 실패합니다. 그래서 당신은 정말로 사용해야 dill
합니다.
import dill
# Save the file
dill.dump(company1, file = open("company1.pickle", "wb"))
# Reload the file
company1_reloaded = dill.load(open("company1.pickle", "rb"))