Tại sao tôi nhận được "Pickle - EOFError: Ran out of input" khi đọc một tệp trống?


109

Tôi gặp một lỗi thú vị khi cố gắng sử dụng Unpickler.load(), đây là mã nguồn:

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

Đây là dấu vết:

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

Tệp tôi đang cố đọc trống. Làm cách nào để tránh gặp phải lỗi này và thay vào đó nhận được một biến trống?


Đừng đóng tập tin
Alkesh Mahajan

Dòng đầu tiên open(...).close()ở đây để đảm bảo tệp tồn tại
Magix

Câu trả lời:


126

Trước tiên, tôi sẽ kiểm tra xem tệp có trống không:

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

Ngoài ra, open(target, 'a').close()không làm gì trong mã của bạn và bạn không cần sử dụng ;.


open (target, 'a'). close () ở đây để đảm bảo tệp tồn tại ;-) + Tôi không cần sử dụng ;nhưng tôi chỉ đến từ C, và việc không sử dụng ;ở cuối dòng khiến tôi phát khóc TT
Magix

ok, nhưng issinstance là không cần thiết như tôi tưởng tượng bạn đang chỉ sẽ được tẩy một dict, kiểm tra đối với một tập tin rỗng sẽ đủ
Padraic Cunningham

hơn nữa, việc kiểm tra tệp không trống không có nghĩa là tôi có thể bỏ chọn nó ... nêu ra một ngoại lệ ... Đó là lý do tại sao tôi không nghĩ câu trả lời của bạn không phải là tốt nhất, thậm chí còn cho rằng nó không tệ.
Magix

2
bắt một EOF exceptionsẽ không giúp bạn tránh khỏi tất cả các lỗi tiềm ẩn khác.
Padraic Cunningham

1
bạn cũng có thể kiểm tra xem tệp có tồn tại hay không bằng cách sử dụng mô-đun hệ điều hành, có thể tốt hơn việc mở và đóng tệp mỗi lần.
Padraic Cunningham

131

Hầu hết các câu trả lời ở đây đều đề cập đến cách xử lý các ngoại lệ EOFError, điều này thực sự hữu ích nếu bạn không chắc chắn về việc đối tượng ngâm có trống hay không.

Tuy nhiên, nếu bạn ngạc nhiên khi thấy tệp pickle trống, có thể là do bạn đã mở tên tệp thông qua 'wb' hoặc một số chế độ khác có thể đã ghi quá nhiều tệp.

ví dụ:

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

Điều này sẽ ghi quá nhiều tệp được ngâm. Bạn có thể đã làm điều này do nhầm lẫn trước khi sử dụng:

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

Và sau đó nhận được lỗi EOFError do khối mã trước đó đã ghi quá nhiều tệp cd.pkl.

Khi làm việc trong Jupyter, hoặc trong bảng điều khiển (Spyder), tôi thường viết một trình bao bọc trên mã đọc / ghi và gọi trình bao bọc sau đó. Điều này tránh các lỗi đọc-ghi phổ biến và tiết kiệm một chút thời gian nếu bạn định đọc cùng một tệp nhiều lần thông qua các travails của mình


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Điều này khiến bạn giành được +1
Neb

10
Tôi vừa làm điều này; thực sự đánh giá cao ghi chú này (Tôi rất vui vì tôi không phải là người duy nhất!)
zlipp

8
cũng đã ghi đè nó trước đây bằng "wb". +1
gebbissimo

5
Đôi khi điều hiển nhiên không hiển nhiên chút nào! Cảm ơn :)
jerpint

Cần thiết phải khóa tệp - Câu trả lời này sẽ giúp ích cho nhiều người, tôi đang cố đọc tệp trong khi nó đang mở để viết.
đầy tham vọng

8

Như bạn thấy, đó thực sự là một lỗi tự nhiên ..

Một cấu trúc điển hình để đọc từ một đối tượng Unpickler sẽ như thế này ..

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

Lỗi EOFError đơn giản chỉ là do nó đang đọc một tệp trống, nó chỉ có nghĩa là End of File ..


7

Rất có thể là tập tin ngâm mình bị trống.

Việc ghi đè lên một tệp pickle dễ dàng một cách đáng ngạc nhiên nếu bạn đang sao chép và dán mã.

Ví dụ sau đây ghi một tệp dưa chua:

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

Và nếu bạn đã sao chép mã này để mở lại, nhưng quên thay đổi 'wb'thành 'rb'thì bạn sẽ ghi đè lên tệp:

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

Cú pháp đúng là

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
Chào mừng bạn đến với Stackoverflow. Bạn có thể giải thích mã này một chút được không?
Alexander

2

Bạn có thể bắt ngoại lệ đó và trả lại bất cứ thứ gì bạn muốn từ đó.

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
Vấn đề với điều này là nó sẽ âm thầm ẩn các tệp bị hỏng.
Ross Ridge,

0

Lưu ý rằng chế độ mở tệp là 'a' hoặc một số chế độ khác có bảng chữ cái 'a' cũng sẽ gây ra lỗi do ghi đè.

pointer = open('makeaafile.txt', 'ab+')
tes = pickle.load(pointer, encoding='utf-8')
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.