เหตุใดฉันจึงได้รับ“ Pickle - EOFError: Ran out of input” อ่านไฟล์เปล่า


115

ฉันได้รับข้อผิดพลาดที่น่าสนใจขณะพยายามใช้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

คำตอบ:


132

ฉันจะตรวจสอบว่าไฟล์ไม่ว่างเปล่าก่อน:

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


เปิด (เป้าหมาย 'a') ปิด () อยู่ที่นี่เพื่อให้แน่ใจว่ามีไฟล์อยู่ ;-) + ฉันไม่จำเป็นต้องใช้;แต่ฉันเพิ่งมาจาก C และไม่ได้ใช้;ที่ท้ายบรรทัดของฉันทำให้ฉันร้องไห้ TT
Magix

โอเค แต่ issinstance นั้นไม่จำเป็นเพราะฉันคิดว่าคุณกำลังจะดอง dict เท่านั้นการตรวจสอบไฟล์เปล่าก็เพียงพอแล้ว
Padraic Cunningham

นอกจากนี้การตรวจสอบไฟล์ไม่ว่างเปล่าไม่ได้หมายความว่าฉันจะยกเลิกการคลิกได้เสมอไป ... เพิ่มข้อยกเว้น ... นั่นเป็นเหตุผลว่าทำไมฉันไม่คิดว่าคำตอบของคุณไม่ดีที่สุดแม้ว่าจะคิดว่ามันไม่เลวก็ตาม
Magix

2
การจับEOF exceptionจะไม่ช่วยให้คุณรอดพ้นจากข้อผิดพลาดอื่น ๆ ที่อาจเกิดขึ้นได้
Padraic Cunningham

1
คุณสามารถตรวจสอบว่ามีไฟล์อยู่หรือไม่โดยใช้โมดูลระบบปฏิบัติการอาจดีกว่าการเปิดและปิดไฟล์ทุกครั้ง
Padraic Cunningham

135

คำตอบส่วนใหญ่เกี่ยวกับวิธีจัดการข้อยกเว้น EOFError ซึ่งมีประโยชน์มากหากคุณไม่แน่ใจว่าวัตถุดองนั้นว่างเปล่าหรือไม่

อย่างไรก็ตามหากคุณประหลาดใจที่ไฟล์ดองว่างเปล่าอาจเป็นเพราะคุณเปิดชื่อไฟล์ผ่าน 'wb' หรือโหมดอื่น ๆ ที่อาจมีการเขียนทับไฟล์

ตัวอย่างเช่น:

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

สิ่งนี้จะเขียนทับไฟล์ดอง คุณอาจทำสิ่งนี้โดยไม่ได้ตั้งใจก่อนใช้:

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

จากนั้นได้รับ EOFError เนื่องจากโค้ดบล็อกก่อนหน้านี้เขียนทับไฟล์ cd.pkl

เมื่อทำงานใน Jupyter หรือในคอนโซล (Spyder) ฉันมักจะเขียน Wrapper ทับรหัสการอ่าน / เขียนและเรียก Wrapper ในภายหลัง วิธีนี้จะหลีกเลี่ยงข้อผิดพลาดในการอ่าน - เขียนทั่วไปและช่วยประหยัดเวลาได้เล็กน้อยหากคุณกำลังจะอ่านไฟล์เดียวกันหลาย ๆ ครั้งผ่านการเดินทางของคุณ


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 ถูกยกขึ้นเพียงเพราะมันกำลังอ่านไฟล์เปล่ามันหมายถึงEnd of File ..


8

เป็นไปได้มากว่าไฟล์ดองว่างเปล่า

มันง่ายมากที่จะเขียนทับไฟล์ดองหากคุณกำลังคัดลอกและวางโค้ด

ตัวอย่างเช่นต่อไปนี้เขียนไฟล์ดอง:

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

และหากคุณคัดลอกรหัสนี้เพื่อเปิดขึ้นมาใหม่ แต่ลืมเปลี่ยน'wb'เป็น'rb'คุณจะเขียนทับไฟล์:

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

ไวยากรณ์ที่ถูกต้องคือ

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

1
ตัวอย่างโค้ดสองตัวสุดท้ายควรจะสลับใช่ไหม
Daniello

@Daniello ฉันทำ. ขอบคุณ. มีการแก้ไข
user2723494

ใช่ฉันทำผิดแบบเดียวกันและผลลัพธ์ทั้งหมดก็พังทลายซึ่งต้องรันการคำนวณก่อนหน้านี้ใหม่ทั้งหมดและรอหนึ่งวันเพื่อให้ได้ผลลัพธ์ น่าเสียดายจริงๆ!
sikisis

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.