1

I have a custom made dictionary. It reloads the whole dictionary each time a field is accessed. For instance, I could have a loop like this:

my_dict=myDict('file.yml')

while(True):
    print(my_dict['field'])

And this will change the output if I modify the file file.conf while running. It is done by inheriting from collections.UserDict and modifying __getitem__ as described in this question. In short, it looks like this:

class myDict(collections.UserDict):
    def __init__(self, filename):
        super().__init__()
        self.config_filename=filename
        self.reload()

    def __getitem__(self, key):
        self.reload() 
        return super().__getitem__(key)

    def reload(self):
        with open(self.config_filename) as f:
             data=yaml.safe_load(f)
        super().__init__(data)

I tried this code:

my_dict=myDict('file.yml')

for e in my_dict['test']:
    print(e)
    time.sleep(5)

While running, I modified the yaml file, but it did not have any effect, which is what I want. But I do wonder how much I can trust this. My assumption here is that my_dict['test'] will only be accessed once in this for loop, which means that my_dict.__getitem__ will only be called once. Is this correct?

I also tried modifying the values within the loop like this:

for e in my_dict['test']:
    print(e)
    print(my_dict['test'][e])
    my_dict['test']['me']='hehehehe'
    time.sleep(5)

At the same time I also modified the file, but none of the changes showed in the printouts. So what's going on here? From my experiments, it seems like the for loop is equivalent to something like:

my_copy = copy.deepcopy(my_dict):
for e in my_copy:

But it feels risky to assume that this is safe.

klutt
  • 30,332
  • 17
  • 55
  • 95
  • 2
    If `reload` only changes the values associated with the existing keys, you should be OK. If `reload` adds or removes a key, that can affect the order of the keys, and your iteration may miss a key or visit a key twice. – chepner Jun 02 '20 at 13:13
  • @chepner So my assumption that it is like a deep copy is false? – klutt Jun 02 '20 at 13:22
  • 1
    Probably. What does exactly does `reload` do? – chepner Jun 02 '20 at 13:24
  • @chepner See updated code – klutt Jun 02 '20 at 13:34
  • 1
    `__init__` will not *remove* keys if they are no longer present in the file, but it can add keys, so it's not safe to call `reload` during iteration. (Regarding the first point, you should probably call `self.clear()`, then `self.update(data)`, to ensure the existing instance reflects the current contents of the file. – chepner Jun 02 '20 at 13:48
  • @chepner Very good to know. You discovered a bug I had no idea about. Maybe you should write a proper answer? – klutt Jun 02 '20 at 16:40
  • @chepner I did a test now and it seems that removals gets through too. Did not try it in a loop though. – klutt Jun 04 '20 at 08:11

0 Answers0