空のファイルを読み取って「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 14

[OK]を、しかしissinstanceは、私はあなただけで十分であろう空のファイルをチェックし、辞書を酸洗しようとしている想像して不要です
パドレイクカニンガム

さらに、ファイルが空でないことを確認しても、常にファイルを取り出すことができるわけではありません。
Magix 14

2
をキャッチEOF exceptionしても、他のすべての潜在的なエラーからあなたを救うことはできません。
Padraic Cunningham 2014

1
osモジュールを使用してファイルが存在するかどうかを確認することもできます。毎回ファイルを開いたり閉じたりするよりも良いでしょう。
Padraic Cunningham 2014

131

ここでの回答のほとんどは、EOFError例外を管理する方法を扱っています。これは、ピクルされたオブジェクトが空であるかどうかわからない場合に非常に便利です。

ただし、pickleファイルが空であることに驚いた場合は、「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ファイルを書き込みます。

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
これの問題は、破損したファイルを静かに隠すことです。
ロス・リッジ

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.