Mengapa saya mendapatkan pesan "Pickle - EOFError: Kehabisan input" saat membaca file kosong?


109

Saya mendapatkan kesalahan yang menarik saat mencoba menggunakan Unpickler.load(), berikut ini kode sumbernya:

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

Inilah traceback:

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

File yang saya coba baca kosong. Bagaimana saya bisa menghindari kesalahan ini, dan mendapatkan variabel kosong sebagai gantinya?


Jangan tutup file
Alkesh Mahajan

Baris pertama open(...).close()ada di sini untuk memastikan file tersebut ada
Magix

Jawaban:


126

Saya akan memeriksa bahwa file tersebut tidak kosong dulu:

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()

Juga open(target, 'a').close()tidak melakukan apa pun dalam kode Anda dan Anda tidak perlu menggunakan ;.


open (target, 'a'). close () ada di sini untuk memastikan file tersebut ada ;-) + Saya tidak perlu menggunakan ;tetapi saya hanya menggunakan C, dan tidak menggunakan ;di akhir baris membuat saya menangis TT
Magix

ok, tapi kesalahan ini tidak diperlukan karena saya membayangkan Anda hanya akan membuat kesalahan, memeriksa file kosong sudah cukup
Padraic Cunningham

lebih jauh lagi, memeriksa file tidak kosong tidak selalu berarti saya dapat melepaskannya ... memunculkan pengecualian ... Itulah mengapa menurut saya jawaban Anda bukan yang terbaik, meskipun menurut saya tidak buruk.
Magix

2
menangkap sebuah EOF exceptiontidak akan menyelamatkan Anda dari semua potensi kesalahan lainnya.
Padraic Cunningham

1
Anda juga dapat memeriksa apakah sebuah file ada menggunakan modul os, mungkin lebih baik daripada membuka dan menutup file setiap saat.
Padraic Cunningham

131

Sebagian besar jawaban di sini telah membahas cara mengatur pengecualian EOFError, yang sangat berguna jika Anda tidak yakin apakah objek yang diawetkan kosong atau tidak.

Namun, jika Anda terkejut bahwa file acar kosong, itu mungkin karena Anda membuka nama file melalui 'wb' atau mode lain yang dapat menimpa file tersebut.

sebagai contoh:

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

Ini akan menimpa file acar. Anda mungkin telah melakukan ini karena kesalahan sebelum menggunakan:

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

Dan kemudian mendapat EOFError karena blok kode sebelumnya menimpa file cd.pkl.

Saat bekerja di Jupyter, atau di konsol (Spyder) saya biasanya menulis pembungkus di atas membaca / menulis kode, dan memanggil pembungkus kemudian. Ini untuk menghindari kesalahan baca-tulis yang umum, dan menghemat sedikit waktu jika Anda akan membaca file yang sama beberapa kali melalui travails Anda


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 fileIni membuat Anda menang +1
Neb

10
Saya baru saja melakukan ini; sangat menghargai catatan ini (saya senang saya bukan satu-satunya!)
zlipp

8
juga telah menimpanya sebelumnya dengan "wb". +1
gebbissimo

5
Terkadang yang jelas tidak terlihat sama sekali! Terima kasih :)
jerpint

kebutuhan penguncian file - Jawaban ini akan membantu banyak orang, saya mencoba membaca file saat terbuka untuk menulis.
aspiring1

8

Seperti yang Anda lihat, itu sebenarnya kesalahan alam ..

Konstruksi tipikal untuk membaca dari objek Unpickler akan seperti ini ..

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

EOFError dimunculkan begitu saja, karena ia membaca file kosong, itu hanya berarti End of File ..


6

Kemungkinan besar file acar tersebut kosong.

Sangat mudah untuk menimpa file acar jika Anda menyalin dan menempelkan kode.

Misalnya yang berikut ini menulis file acar:

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

Dan jika Anda menyalin kode ini untuk membukanya kembali, tapi lupa untuk perubahan 'wb'ke 'rb'maka Anda akan menimpa file:

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

Sintaks yang benar adalah

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

1
Dua contoh kode terakhir harus ditukar, bukan?
Daniello

@Daniello saya lakukan. Terima kasih. Ini direvisi.
user2723494

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
Halo dan selamat datang di Stackoverflow. Bisakah Anda menjelaskan sedikit kode ini?
Alexander

2

Anda dapat menangkap pengecualian itu dan mengembalikan apa pun yang Anda inginkan dari sana.

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
Masalahnya adalah ini akan menyembunyikan file yang rusak secara diam-diam.
Ross Ridge

0

Perhatikan bahwa mode membuka file adalah 'a' atau beberapa lainnya memiliki alfabet 'a' juga akan membuat kesalahan karena penimpaan.

pointer = open('makeaafile.txt', 'ab+')
tes = pickle.load(pointer, encoding='utf-8')
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.