Reputation: 8142
Is there a better way to load a variable with pickle
if it already exists or create it and dump it if it doesn't?
if os.path.isfile("var.pickle"):
foo = pickle.load( open( "var.pickle", "rb" ) )
else:
foo = 3
pickle.dump( foo, open( "var.pickle", "wb" ) )
Upvotes: 25
Views: 28685
Reputation: 395633
I'd put it in a function for reusability, avoid error catching for control flow on the file, as it's less efficient, and I would use context managers to open the file.
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 Exception: # so many things could go wrong, can't be more specific.
pass
with open(path, "wb") as f:
pickle.dump(default, f)
return default
usage:
foo = read_or_new_pickle(path="var.pickle", default=3)
foo
returns 3
foo = read_or_new_pickle(path="var.pickle", default=4)
and foo
still returns 3
.
Admittedly, the following is rather short and elegant, but too many things could go wrong, and you'd have to catch everything (don't believe me? try this: import io, pickle; pickle.load(io.BytesIO(b"\x00"))
and play with the binary):
import pickle
def read_or_new_pickle(path, default):
try:
foo = pickle.load(open(path, "rb"))
except Exception:
foo = default
pickle.dump(foo, open(path, "wb"))
return foo
Same usage. But I'm concerned the file might not be closed fast enough to avoid an error on opening it the second time in the event of a empty or malformed file. So use the context manager:
import pickle
def read_or_new_pickle(path, default):
try:
with open(path, "rb") as f:
foo = pickle.load(f)
except Exception:
foo = default
with open(path, "wb") as f:
pickle.dump(foo, f)
return foo
Upvotes: 9
Reputation: 474131
You can follow the EAFP
principle and ask for forgiveness:
import pickle
try:
foo = pickle.load(open("var.pickle", "rb"))
except (OSError, IOError) as e:
foo = 3
pickle.dump(foo, open("var.pickle", "wb"))
Upvotes: 44