빈 파일을 읽을 때 "Pickle-EOFError : Ran out of input"이 발생하는 이유는 무엇입니까?


109

를 사용하는 동안 흥미로운 오류가 발생합니다 Unpickler.load(). 다음은 소스 코드입니다.

open(target, 'a').close()
scores = {};
with open(target, "rb") as file:
    unpickler = pickle.Unpickler(file);
    scores = unpickler.load();
    if not isinstance(scores, dict):
        scores = {};

다음은 역 추적입니다.

Traceback (most recent call last):
File "G:\python\pendu\user_test.py", line 3, in <module>:
    save_user_points("Magix", 30);
File "G:\python\pendu\user.py", line 22, in save_user_points:
    scores = unpickler.load();
EOFError: Ran out of input

읽으려는 파일이 비어 있습니다. 이 오류가 발생하지 않고 대신 빈 변수를 얻을 수있는 방법은 무엇입니까?


파일을 닫지 마십시오
Alkesh Mahajan

첫 번째 줄 open(...).close()은 파일이 존재하는지 확인하기 위해 여기에 있습니다
Magix

답변:


126

먼저 파일이 비어 있지 않은지 확인합니다.

import os

scores = {} # scores is an empty dict already

if os.path.getsize(target) > 0:      
    with open(target, "rb") as f:
        unpickler = pickle.Unpickler(f)
        # if file is not empty scores will be equal
        # to the value unpickled
        scores = unpickler.load()

또한 open(target, 'a').close()코드에서 아무것도하지 않으며 ;.


open (target, 'a'). close ()는 파일이 존재하는지 확인하기 위해 여기에 있습니다 ;-) + 사용할 필요는 ;없지만 C에서 왔고 ;내 줄 끝에서 사용하지 않고 외침 TT
Magix 2014

좋아,하지만 issinstance 난 당신 만 충분 빈 파일을 확인하는 딕셔너리를 산세 할 예정 상상 불필요
Padraic 커닝햄

또한 파일이 비어 있지 않은지 확인한다고해서 항상 파일을 해제 할 수있는 것은 아닙니다. 예외를 발생시킵니다 ... 그래서 귀하의 답변이 최고가 아니라고 생각하고 나쁘지 않다고 생각합니다.
Magix

2
를 잡는 것은 EOF exception다른 모든 잠재적 인 오류로부터 당신을 구할 수 없습니다.
Padraic Cunningham

1
os 모듈을 사용하여 파일이 있는지 확인할 수 있습니다. 매번 파일을 열고 닫는 것보다 낫습니다.
Padraic Cunningham

131

여기에있는 대부분의 답변은 EOFError 예외를 관리하는 방법을 다루었습니다. 피클 된 객체가 비어 있는지 여부가 확실하지 않은 경우 정말 편리합니다.

그러나 피클 파일이 비어 있다는 사실에 놀란다면 'wb'또는 파일을 덮어 쓸 수있는 다른 모드를 통해 파일 이름을 열었 기 때문일 수 있습니다.

예를 들면 :

filename = 'cd.pkl'
with open(filename, 'wb') as f:
    classification_dict = pickle.load(f)

절인 파일을 덮어 씁니다. 다음을 사용하기 전에 실수로이 작업을 수행했을 수 있습니다.

...
open(filename, 'rb') as f:

그리고 이전 코드 블록이 cd.pkl 파일을 덮어 썼기 때문에 EOFError가 발생했습니다.

Jupyter 또는 콘솔 (Spyder)에서 작업 할 때 일반적으로 읽기 / 쓰기 코드 위에 래퍼를 작성하고 나중에 래퍼를 호출합니다. 이렇게하면 일반적인 읽기-쓰기 실수를 피할 수 있으며 고생을 통해 동일한 파일을 여러 번 읽을 경우 시간을 절약 할 수 있습니다.


43
However, if you're surprised that the pickle file is empty, it could be because you opened the filename through 'wb' or some other mode that could have over-written the file이로 인해 +1
Neb

10
난 그냥 했어요 정말 (내가 유일한 사람이 아니에요 다행이야!)이 쪽지를 주셔서 감사합니다
zlipp

8
이전에 "wb"로 덮어 썼습니다. +1
gebbissimo

5
때로는 명백한 것이 전혀 분명하지 않습니다! 감사합니다 :)
jerpint

파일 잠금 필요성 -이 대답은 많은 사람들에게 도움이 될 것입니다. 파일이 쓰기 위해 열려있는 동안 파일을 읽으려고했습니다.
aspiring1

8

보시다시피 그것은 실제로 자연스러운 오류입니다 ..

Unpickler 객체에서 읽기위한 일반적인 구조는 다음과 같습니다.

try:
    data = unpickler.load()
except EOFError:
    data = list()  # or whatever you want

참고 EOFError는 단순히 발생이 빈 파일을 읽기 때문에, 그것은 단지 의미가 파일의 끝을 ...


7

절인 파일이 비어있을 가능성이 큽니다.

코드를 복사하여 붙여 넣는 경우 피클 파일을 덮어 쓰는 것은 놀랍도록 쉽습니다.

예를 들어 다음은 피클 파일을 작성합니다.

pickle.dump(df,open('df.p','wb'))

이 코드를 복사하여 다시 열었지만 변경 'wb'하는 것을 잊은 'rb'경우 파일을 덮어 쓰게됩니다.

df=pickle.load(open('df.p','rb'))

올바른 구문은 다음과 같습니다.

df=pickle.load(open('df.p','wb'))

3
if path.exists(Score_file):
      try : 
         with open(Score_file , "rb") as prev_Scr:

            return Unpickler(prev_Scr).load()

    except EOFError : 

        return dict() 

2
안녕하세요, Stackoverflow에 오신 것을 환영합니다. 이 코드를 조금 설명해 주시겠습니까?
Alexander는

2

해당 예외를 포착하고 거기에서 원하는 것을 반환 할 수 있습니다.

open(target, 'a').close()
scores = {};
try:
    with open(target, "rb") as file:
        unpickler = pickle.Unpickler(file);
        scores = unpickler.load();
        if not isinstance(scores, dict):
            scores = {};
except EOFError:
    return {}

10
이것의 문제는 손상된 파일을 조용히 숨길 것이라는 것입니다.
Ross Ridge

0

파일을 여는 모드가 'a'이거나 다른 일부가 알파벳 'a'를 가지고 있으면 덮어 쓰기 때문에 오류가 발생합니다.

pointer = open('makeaafile.txt', 'ab+')
tes = pickle.load(pointer, encoding='utf-8')
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.