-1

After changing a value in a dict i'd like to automatically save that dict to a file. I already do the saving to file but how to detect the change and trigger the saving?

I'm using Python 3.7

Endogen
  • 589
  • 2
  • 12
  • 24
  • 1
    What do you mean by detect the change? Is the dictionary being updated asynchronously in multiple parallel threads? – justhalf Aug 23 '18 at 21:35
  • 1
    you can use a callback method or event to save the dict. see this https://stackoverflow.com/questions/1092531/event-system-in-python – Jefferson Puchalski Aug 23 '18 at 21:39
  • 3
    Write your own `dict` subclass that overrides `__setitem__`. You can have it do whatever you want before or after calling `super().__setitem__`, like opening some file to `json.dump(self, f)`, or calling some callback function that you stored during `__init__`, or anything else you want. – abarnert Aug 23 '18 at 21:39
  • 1
    Another thing you might want to consider if your keys and values are all strings is using a `dbm` instead of a dict. Or if your keys are all strings and your values are not strings but are all reasonably small and pickleable, a `shelve`. – abarnert Aug 23 '18 at 21:41
  • 1
    Possible duplicate of [Python Property Change Listener Pattern](https://stackoverflow.com/questions/5186520/python-property-change-listener-pattern) – Scott Mermelstein Aug 23 '18 at 21:41
  • @justhalf No. i mean, if i change something in that dict i want to automatically save it to a file. Currently i have to do the saving on my own. I have to change the value and then save the content to a file. That saving should be automatic now so i have to detect the changing of the dict to being able to save it immediately after the change - that's at least my undersanding – Endogen Aug 23 '18 at 21:42
  • 2
    If you can just use a `dbm` or `shelve`, this is trivial—just do that. If your keys aren't strings, or your values are huge or non-picklable objects, then you can't. In which case, this is basically a dup of the question @ScottMermelstein linked above, or at any rate you can use the answer from that question. – abarnert Aug 23 '18 at 21:45
  • Fortunately an automatically saving dict was already invented, it's called a database. – wim Aug 23 '18 at 22:06
  • @wim nice one :-) but not an option. i want to be able to change values with just a text editor – Endogen Aug 23 '18 at 22:18
  • @abarnert i'd like to mark your answer as the right one but you have to post it as an answer first. thanks – Endogen Aug 24 '18 at 11:28
  • @Endogen Nobody can answer your question while it's closed. You need to [edit] it to answer the questions raised by the people who voted to close, and to generally be clearer about exactly what you're trying to accomplish, and they should vote to reopen the question. – abarnert Aug 24 '18 at 17:40

1 Answers1

2

One option is to do the file writing at all points in your code where the dict is modified.

An alternative is to use custom methods with a decorator to make any changes to the dictionary. This would look something like:

import json
import functools

# decorator to save functions return value to a file.
def decorated_change(func):
    @functools.wraps(func)
    def wrap(*args, **kwargs):
        f = func(*args, **kwargs)
        with open('file.txt', 'w') as file:
            file.write(json.dumps(f))
    return wrap

@decorated_change
def set_dict_entry(dict, key, value):
    dict[key] = value

Ideally you would create your own dictionary class, and apply a similar decorator to the setitem method like so:

class modified_dict(dict):
    @some_decorator
    def __setitem__(self, i, y):
        super().__setitem__

And additionally as others have pointed out you could simply forgo the decorator all together:

class modified_dict(dict):
    def __setitem__(self, key, value):
        super().__setitem__(key, value)
        with open('file.txt', 'w') as f:
            file.write(json.dumps(f, indent=4, sort_keys=True))

But if you plan on applying this type of mechanism on other data structures, it might be better to go with the decorator to adhere to DRY principles.

wenzul
  • 3,948
  • 2
  • 21
  • 33
Philip DiSarro
  • 1,007
  • 6
  • 9