개체 저장 및로드 및 피클 사용


114

pickle모듈을 사용하여 개체를 저장하고로드하려고 합니다.
먼저 객체를 선언합니다.

>>> class Fruits:pass
...
>>> banana = Fruits()

>>> banana.color = 'yellow'
>>> banana.value = 30

그 후 'Fruits.obj'라는 파일을 엽니 다 (이전에는 새 .txt 파일을 만들고 이름을 'Fruits.obj'로 변경했습니다).

>>> import pickle
>>> filehandler = open(b"Fruits.obj","wb")
>>> pickle.dump(banana,filehandler)

이 작업을 수행 한 후 세션을 닫고 새 세션을 시작하고 다음 세션을 넣습니다 (저장해야하는 개체에 액세스하려고 시도 함).

file = open("Fruits.obj",'r')
object_file = pickle.load(file)

하지만이 메시지가 있습니다.

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python31\lib\pickle.py", line 1365, in load
encoding=encoding, errors=errors).load()
ValueError: read() from the underlying stream did notreturn bytes

이 메시지를 이해하지 못하기 때문에 어떻게해야할지 모르겠습니다. 누구든지 내 개체 '바나나'를로드 할 수있는 방법을 알고 있습니까? 감사합니다!

편집하다 : 여러분 중 일부는 다음 같이 말했습니다.

>>> import pickle
>>> file = open("Fruits.obj",'rb')

문제는 없었지만 다음은 다음과 같습니다.

>>> object_file = pickle.load(file)

그리고 오류가 있습니다.

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python31\lib\pickle.py", line 1365, in load
encoding=encoding, errors=errors).load()
EOFError


답변:


74

두 번째 문제는 다음과 같습니다.

 Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 File "C:\Python31\lib\pickle.py", line
 1365, in load encoding=encoding,
 errors=errors).load() EOFError

파일의 내용을 읽은 후에는 파일 포인터가 파일의 끝에있게되며 더 이상 읽을 데이터가 없습니다. 처음부터 다시 읽을 수 있도록 파일을 되 감아 야합니다.

file.seek(0)

하지만 일반적으로 원하는 것은 컨텍스트 관리자를 사용하여 파일을 열고 데이터를 읽는 것입니다. 이렇게하면 블록 실행이 완료된 후 파일이 자동으로 닫히므로 파일 작업을 의미있는 청크로 구성하는 데 도움이됩니다.

마지막으로, cPickle은 C에서 pickle 모듈의 더 빠른 구현입니다. 따라서 :

In [1]: import cPickle

In [2]: d = {"a": 1, "b": 2}

In [4]: with open(r"someobject.pickle", "wb") as output_file:
   ...:     cPickle.dump(d, output_file)
   ...:

# pickle_file will be closed at this point, preventing your from accessing it any further

In [5]: with open(r"someobject.pickle", "rb") as input_file:
   ...:     e = cPickle.load(input_file)
   ...:

In [7]: print e
------> print(e)
{'a': 1, 'b': 2}

이 'd = { "a": 1, "b": 2}'는 어떤 종류의 데이터 구조입니까?
Peterstone

1
@Peterstone : {"a": 1, "b": 2}"a"와 그 "b"안에 있는 사전을 만듭니다 . 온라인 문서 에서는이를 사전 표시 표현식 이라고합니다 . 이것은 dict파이썬에서 사용할 수있는 여러 표준 내장 데이터 유형 중 하나 인 유형의 객체를 구성 할 수있는 여러 가지 방법 중 하나 일뿐 입니다.
martineau 2010

2
문자 'r'이 파일 이름을 계속하는 이유는 무엇입니까? 나는 문서에서 그것을 보지 않는다. 또한 파일 이름에 변수를 사용하기 어렵게 만듭니다.
SherylHohman 2017-04-27

7
오늘이 답변을 살펴보면 Python 2.x에만 적용됩니다. Python 3.x에서는 가능 하면 자동으로 pickle가져 오는 것을 직접 사용해야 합니다 cpickle. docs.python.org/3.1/whatsnew/3.0.html#library-changes
Eskapp

41

다음은 나를 위해 작동합니다.

class Fruits: pass

banana = Fruits()

banana.color = 'yellow'
banana.value = 30

import pickle

filehandler = open("Fruits.obj","wb")
pickle.dump(banana,filehandler)
filehandler.close()

file = open("Fruits.obj",'rb')
object_file = pickle.load(file)
file.close()

print(object_file.color, object_file.value, sep=', ')
# yellow, 30

이것은 저에게 효과적이지만 제가 추구하는 것은 세션을 닫고 새 세션을 열고 지난 세션에서 저장 한 것을로드하는 것입니다. "filehandler.close ()"줄을 넣은 후 세션을 닫고 새 줄을 열고 나머지 코드를 넣은 다음 "object_file = pickle.load (file)"을 넣은 후이 오류가 발생합니다. 가장 최근 호출 last) : 파일 "<pyshell # 5>", 줄 1, <module> object_file = pickle.load (file) 파일 "C : \ Python31 \ lib \ pickle.py", 줄 1365,로드 인코딩 = encoding, errors = errors) .load () AttributeError : '모듈'개체에 'Fruits'속성이 없습니다
Peterstone

3
@Peterstone : 두 번째 세션 에서는 이진 파일에 저장된 데이터에서 개체를 재구성 할 수 class Fruits있도록 정의 된 정의가 필요 pickle.load()합니다. 이러한 종류의 가장 좋은 방법은 class Fruits정의를 별도의 .py 파일 (사용자 정의 모듈로 만들기)에 넣은 다음 import필요할 때마다 해당 모듈 또는 항목 (즉, 두 세션 모두) 에 넣는 것입니다 . 예를 들어, 당신은라는 이름의 파일에 넣어 경우 MyDataDefs.py다음 쓸 수 있습니다 from MyDataDefs import Fruits. 이것이 명확하지 않은 경우 알려 주시면 그에 따라 답변을 업데이트하겠습니다.
martineau 2011 년

실제로 PEP 8 은 모듈 이름에 모두 소문자를 사용하도록 권장 하므로 마지막 주석 끝에있는 예제는 my_data_defs.pyusing 이라는 파일에 있어야합니다 from my_data_defs import Fruits.
martineau 2015 년

24

바이너리로 읽는 것을 잊고 있습니다.

쓰기 부분에는 다음이 있습니다.

open(b"Fruits.obj","wb") # Note the wb part (Write Binary)

읽기 부분에는 다음이 있습니다.

file = open("Fruits.obj",'r') # Note the r part, there should be a b too

따라서 다음으로 대체하십시오.

file = open("Fruits.obj",'rb')

그리고 그것은 작동합니다 :)


두 번째 오류는 파일을 제대로 닫거나 동기화하지 않아서 발생할 가능성이 큽니다.

다음 코드를 작성해보십시오.

>>> import pickle
>>> filehandler = open(b"Fruits.obj","wb")
>>> pickle.dump(banana,filehandler)
>>> filehandler.close()

그리고 이것은 (변경되지 않음) 읽을 수 있습니다.

>>> import pickle
>>> file = open("Fruits.obj",'rb')
>>> object_file = pickle.load(file)

깔끔한 버전은 with문을 사용합니다 .

쓰기 :

>>> import pickle
>>> with open('Fruits.obj', 'wb') as fp:
>>>     pickle.dump(banana, fp)

읽기 :

>>> import pickle
>>> with open('Fruits.obj', 'rb') as fp:
>>>     banana = pickle.load(fp)

1
with 문을 사용하는 버전을 사용하면 다음 메시지가 나타납니다. Traceback (most recent call last) : File "<pyshell # 20>", line 1, in <module> print (banana.color) AttributeError : 'Fruits' 개체에 '색상'속성이 없습니다
Peterstone

17

이 경우 항상 바이너리 모드로 엽니 다.

file = open("Fruits.obj",'rb')

6

바이너리 모드에서 파일을 열지 않았습니다.

open("Fruits.obj",'rb')

작동해야합니다.

두 번째 오류의 경우 파일이 비어있을 가능성이 높습니다. 이는 실수로 파일을 비우거나 잘못된 파일 이름 등을 사용했음을 의미합니다.

(이것은 당신이 정말로 세션을 닫았다 고 가정합니다. 그렇지 않다면 쓰기와 읽기 사이에 파일을 닫지 않았기 때문입니다).

귀하의 코드를 테스트했으며 작동합니다.


3

세션 전반에 걸쳐 클래스 인스턴스를 저장하려는 것 같으며 사용하는 pickle것이 적절한 방법입니다. 그러나 klepto사전 인터페이스에 개체 저장을 추상화 하는 패키지가 있으므로 개체를 선택하여 파일에 저장하거나 (아래 그림 참조) 개체를 선택하여 데이터베이스에 저장하거나 pickle use json 또는 다른 많은 옵션을 사용하십시오. 좋은 점은 klepto공통 인터페이스로 추상화함으로써 쉽게 파일에 피클 링을 통해 저장하는 방법에 대한 낮은 수준의 세부 정보를 기억할 필요가 없다는 것입니다.

동적으로 추가 된 클래스 속성에 대해 작동하지만 pickle은 수행 할 수 없습니다.

dude@hilbert>$ python
Python 2.7.6 (default, Nov 12 2013, 13:26:39) 
[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.
>>> from klepto.archives import file_archive 
>>> db = file_archive('fruits.txt')
>>> class Fruits: pass
... 
>>> banana = Fruits()
>>> banana.color = 'yellow'
>>> banana.value = 30
>>> 
>>> db['banana'] = banana 
>>> db.dump()
>>> 

그런 다음 다시 시작합니다 ...

dude@hilbert>$ python
Python 2.7.6 (default, Nov 12 2013, 13:26:39) 
[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.
>>> from klepto.archives import file_archive
>>> db = file_archive('fruits.txt')
>>> db.load()
>>> 
>>> db['banana'].color
'yellow'
>>> 

Klepto python2 및 python3에서 작동합니다.

여기에서 코드 받기 : https://github.com/uqfoundation


1

anycache 를 사용 하여 작업을 수행 할 수 있습니다 . myfunc인스턴스를 생성 하는 함수가 있다고 가정합니다 .

from anycache import anycache

class Fruits:pass

@anycache(cachedir='/path/to/your/cache')    
def myfunc()
    banana = Fruits()
    banana.color = 'yellow'
    banana.value = 30
return banana

Anycache myfunc는 처음에 호출 cachedir하고 고유 식별자 (함수 이름 및 인수에 따라 다름)를 파일 이름 으로 사용하여 결과를 파일로 피클합니다 . 연속 실행시 피클 된 개체가로드됩니다.

이 경우 cachedir파이썬 실행 사이의 보존, 절임 객체는 이전 파이썬 실행에서 가져옵니다.

함수 인수도 고려됩니다. 리팩토링 된 구현은 다음과 같이 작동합니다.

from anycache import anycache

class Fruits:pass

@anycache(cachedir='/path/to/your/cache')    
def myfunc(color, value)
    fruit = Fruits()
    fruit.color = color
    fruit.value = value
return fruit
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.