Pooling

singlejson.load() returns a shared instance per absolute path, so different parts of your code operate on the same in-memory object.

Read more about defaults in Default handling
import singlejson

a = singlejson.load("shared.json", default_data={})
b = singlejson.load("shared.json") # Will get the same default_data
# but only if a was initialized first (!) use default_path to ensure consistency!
print(a is b)  # > True

You can do multiple operations on the entire pool of loaded files using singlejson.sync() and singlejson.reset() to clear the pool with and without saving.

When you need to keep a copy of the on-disk file before recovery overwrites it, pass preserve=True (or None to defer to the instance setting) to singlejson.load(); backups are written as <name>.old.<n>.json.

You can also use singlejson.close() to remove a specific file from the pool.

I like to use singlejson.sync() at program exit with a 3 second wait to give the user time to cancel all pending writes in case of unwanted changes.

Example usage sync with sleep
from singlejson import load, sync
from time import sleep

# Load shared instance
settings = load("settings.json", default_data={"theme": "dark"})
settings.json["theme"] = "light"  # modify in memory

# Sync all loaded files to disk
print("Saving, press Ctrl+C to cancel...")
sleep(3)
sync()