Skip to content

Instantly share code, notes, and snippets.

@Beormund
Last active August 1, 2022 11:06
Show Gist options
  • Save Beormund/12c70a3bed7662c72761df9ba3a372ef to your computer and use it in GitHub Desktop.
Save Beormund/12c70a3bed7662c72761df9ba3a372ef to your computer and use it in GitHub Desktop.
Simple micropython module to persist dictionary data to flash and automatically load from flash on restart/import. Tested for RP2 Pico W
import json
persist = None
class Persist(object):
__persist = None
__filename = '__persist__.json'
__p = {}
def __new__(self, d = None):
if self.__persist is None:
self.__persist = super(Persist, self).__new__(self)
if isinstance(d, dict):
# No deepcopy implemented so use json
self.__persist.__p = json.loads(json.dumps(d))
self.__persist.load()
return self.__persist
def __setattr__(self, key, value):
self.__p[key] = value
def __getattr__(self, key):
return self.__p.get(key)
def __getitem__(self, key):
return self.__p[key]
def __setitem__(self, key, value):
self.__p[key] = value
def clear(self):
self.__p.clear()
def has(self, key):
return key in self.__p
def find(self, key):
return self.__p.get(key)
def remove(self, key):
return self.__p.pop(key, 'Key not found')
def load(self):
f = None
val = None
if self.path_exists(self.__filename):
try:
f = open(self.__filename, 'r')
val = json.load(f)
f.close()
except Exception as e:
if f is not None:
f.close()
raise e
if isinstance(val, dict):
object.__setattr__(self, '__p', val)
else:
print(f'Failed to load {self.__filename}')
else:
self.save()
def save(self):
f = None
try:
f = open(self.__filename, 'w')
json.dump(self.__p if isinstance(self.__p, dict) else {}, f)
f.close()
except Exception as e:
if f is not None:
f.close()
raise e
def data(self):
return json.loads(json.dumps(self.__p))
def json(self):
return json.dumps(self.__p)
def path_exists(self, path):
import uos
parent = "" # parent folder name
name = path # name of file/folder
# Check if file/folder has a parent folder
index = path.rstrip('/').rfind('/')
if index >= 0:
index += 1
parent = path[:index]
name = path[index:]
# return name in uos.listdir(parent)
return any((name == x[0]) for x in uos.ilistdir(parent))
persist = Persist()
@Beormund
Copy link
Author

Beormund commented Aug 1, 2022

HOW TO USE:

from persist import persist

# Data is automatically loaded from flash on import

# This will be an empty dictionary when persist module first used
print(persist.data())
# {}
# {'a': 'setting value 1', 'c': {'a': 1, 'b': 2}, 'b': [1, 2, 3]}

# Clears all data
persist.clear()

# Data can be set by attribute name or subscriptable name
persist.a = 'setting value 1'
persist.b = [1,2,3]
persist.c = {'a': 1, 'b': 2}
persist['d'] = 1

# Subscriptable access
print(persist['a'])
# setting value 1

# Attribute access
print(persist.b)
# [1, 2, 3]

# Does persist have a 'b' key?
print(persist.find('b'))
# [1, 2, 3]

print(persist.find('z'))
# None

print(persist.has('z'))
# False

print(persist.remove('d'))
# 1

# returns a dictionary copy of the data
d = persist.data()

# Gets data as a json string
print(persist.json())
# {'a': 'setting value 1', 'c': {'a': 1, 'b': 2}, 'b': [1, 2, 3]}

# Persists data to flash (loads from flash on import AFTER restart)
persist.save()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment