Pickle - загрузить переменную, если она существует, или создать и сохранить ее

Есть ли лучший способ загрузить переменную с помощью pickle, если она уже существует или создать ее, и сбрасывать ее, если это не так?

if os.path.isfile("var.pickle"):
    foo = pickle.load( open( "var.pickle", "rb" ) )
else:
    foo = 3
    pickle.dump( foo, open( "var.pickle", "wb" ) )

Ответ 1

Вы можете следовать принципу EAFP и просить прощения:

import pickle

try:
    foo = pickle.load(open("var.pickle", "rb"))
except (OSError, IOError) as e:
    foo = 3
    pickle.dump(foo, open("var.pickle", "wb"))

Ответ 2

Я бы поставил его в функцию для повторного использования, избегаю ловушки ошибок для потока управления файлом, поскольку он менее эффективен, и я бы использовал диспетчеры контекста, чтобы открыть файл.

import os
import pickle

def read_or_new_pickle(path, default):
    if os.path.isfile(path):
        with open(path, "rb") as f:
            try:
                return pickle.load(f)
            except StandardError: # so many things could go wrong, can't be more specific.
                pass 
    with open(path, "wb") as f:
        pickle.dump(default, f)
    return default

использование:

foo = read_or_new_pickle(path="var.pickle", default=3)

foo возвращает 3

foo = read_or_new_pickle(path="var.pickle", default=4)

и foo все еще возвращает 3.

Правда, следующее довольно короткое и изящное, но слишком много вещей может пойти не так, и вам придется поймать все (не верьте мне: попробуйте это: import io, pickle; pickle.load(io.BytesIO(b"\x00")) и играйте с двоичным кодом):

import pickle

def read_or_new_pickle(path, default):
    try:
        foo = pickle.load(open(path, "rb"))
    except StandardError:
        foo = default
        pickle.dump(foo, open(path, "wb"))
    return foo

То же использование. Но я обеспокоен тем, что файл не может быть закрыт достаточно быстро, чтобы избежать ошибки при открытии его во второй раз в случае пустого или искаженного файла. Поэтому используйте диспетчер контекстов:

import pickle

def read_or_new_pickle(path, default):
    try:
        with open(path, "rb") as f:
            foo = pickle.load(f)
    except StandardError:
        foo = default
        with open(path, "wb") as f:
            pickle.dump(foo, f)
    return foo