Home > Software design >  Problem with comparing two dictionaries? I'm not sure (?)
Problem with comparing two dictionaries? I'm not sure (?)

Time:03-13

I'm really basic with python and trying to make some simple companion for 'Elite: Dangerous' PC game. The game itself writes log files and one of them is 'status.json'. Whole content of file takes one line and is completely overwritten when changed. Here I'm trying to write a code which will read that file, convert it to python dictionary and watch the file for changes.

I'm lookig for changes by simply comparing last readed content of file, stored then as variable 'cache', to newly readed content. The problem seems to be there.

import json


path = 'C:\\Users\\USERNAME\\Saved Games\\Frontier Developments\\Elite Dangerous'


def json_reader(): #function returns WHOLE status.json as python dictionary

    with open(path   '\\status.json', 'r') as line:
        data = json.load(line)
        return data.items()
    
cache = json_reader() #initial flags

for keys, values in cache: print(keys, values) 

while True: #flags monitor
    if cache != json_reader():
        print('\nCHANGES!')
        for keys, values in cache: print(keys, values)

    cache = json_reader()

So far my code reads file, converts it into python dictionary but crashes when file changes... The problem is I don't understand what the problem is. Error looks like that:

Traceback (most recent call last):
  File "C:\Sync\Projekty\Elite Dangerous\Python\ED Assistant\status_reader.py", line 72, in <module>
    cache = json_reader()
  File "C:\Sync\Projekty\Elite Dangerous\Python\ED Assistant\status_reader.py", line 58, in json_reader
    data = json.load(line)
  File "C:\Program Files\Python310\lib\json\__init__.py", line 293, in load
    return loads(fp.read(),
  File "C:\Program Files\Python310\lib\json\__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "C:\Program Files\Python310\lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "C:\Program Files\Python310\lib\json\decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

Examples of status.json That worked:

{ "timestamp":"2022-03-11T09:13:16Z", "event":"Status", "Flags":16777240, "Flags2":2, "Pips":[4,4,4], "FireGroup":0, "GuiFocus":0, "Fuel":{ "FuelMain":8.000000, "FuelReservoir":0.360000 }, "Cargo":0.000000, "LegalState":"Clean", "Balance":962835999, "Destination":{ "System":2553114757483, "Body":43, "Name":"Cottenot City" } }

And when this appeared on status.json it showed an error:

{ "timestamp":"2022-03-11T09:16:31Z", "event":"Status", "Flags":16842765, "Flags2":2, "Pips":[4,4,4], "FireGroup":0, "GuiFocus":0, "Fuel":{ "FuelMain":8.000000, "FuelReservoir":0.360000 }, "Cargo":0.000000, "LegalState":"Clean", "Balance":962835999, "Destination":{ "System":2553114757483, "Body":43, "Name":"Cottenot City" } }

Looking similar but content is not the same

But When I runned code again it handled that file without problem and crashed with next change

CodePudding user response:

Got it!

What I made is putting all code in single try except instead of two.

import json, time


path = 'C:\\Users\\krakers\\Saved Games\\Frontier Developments\\Elite Dangerous'


def json_reader(): #function returns WHOLE status.json as python dictionary

    with open(path   '\\status.json', 'r', encoding='utf-8') as line:
        data = json.load(line)
        return data.items()
    
while True:
    try:
        flags = json_reader()
        print('\nCURRENT FLAGS:')
        for keys, values in flags: print(keys, values)


        while True: 
            json_reader() #repeating function and waiting for error (empty file = being modified)
                
    except json.decoder.JSONDecodeError:
        print('\nCHANGES!')
        time.sleep(0.1) 

The output now is:

CURRENT FLAGS:
timestamp 2022-03-12T17:54:45Z
event Status
Flags 16842760
Flags2 2
Pips [8, 4, 0]
FireGroup 0
GuiFocus 0
Fuel {'FuelMain': 4.097736, 'FuelReservoir': 0.36}
Cargo 0.0
LegalState Clean
Balance 961311284
Destination {'System': 241828881596, 'Body': 51, 'Name': 'Gehry Dock'}

CHANGES!

CURRENT FLAGS:
timestamp 2022-03-12T17:55:09Z
event Status
Flags 16842764
Flags2 2
Pips [8, 4, 0]
FireGroup 0
GuiFocus 0
Fuel {'FuelMain': 4.097736, 'FuelReservoir': 0.36}
Cargo 0.0
LegalState Clean
Balance 961311284
Destination {'System': 241828881596, 'Body': 51, 'Name': 'Gehry Dock'}

CHANGES!

CURRENT FLAGS:
timestamp 2022-03-12T17:55:21Z
event Status
Flags 16842765
Flags2 2
Pips [4, 6, 2]
FireGroup 0
GuiFocus 0
Fuel {'FuelMain': 4.097736, 'FuelReservoir': 0.36}
Cargo 0.0
LegalState Clean
Balance 961311284
Destination {'System': 241828881596, 'Body': 51, 'Name': 'Gehry Dock'}

It still doesn't work as intended. I need to work on it, but my main issue is solved. Thank all of You for help

Actually what I achieved here is using error I tried to manage as indicator of changes in file content.

CodePudding user response:

Looking at the error and your process, my guess is that your are checking the content of the file at a wrong time, file being edited or empty concurently ...

Does the error cause Elite to crash or something ?

It's always a good coding practice to surround sensitive sections with try and except. json.decoder.JSONDecodeError being often caused by empty file or bad encoding, depending on your use case, you could tell your code to wait for a bit of time when this error occurs. Again, all of this relies on this error not causing other problems.

while True: #flags monitor
    try:
        if cache != json_reader():
            print('\nCHANGES!')
            for keys, values in cache: print(keys, values)
        cache = json_reader()
    except json.decoder.JSONDecodeError:
        time.sleep(100)  # Depending on how often the file is supposed to change

But as @ewong stated in the comments, the file looks legit for this specific error to happen.

  • Related