SD card text files evaluated wrong

This has got to be the weirdest and most frustrating bug I have ever come across.

My code is very simple. It uses eval() to turn the contents of a text file into a dictionary, and assigns that dictionary to a variable. It looks like this:

try:
    with open("/ROBOT2/settings.txt", 'r') as file:
        settings = eval(file.read())
        print(settings)
except FileNotFoundError:
    settings = {
    'Exit': None,
    'Turn Reduction': 10,
    'Start Phase': 'STRT',
    'Smart Focus': False,
    'Smart Shutoff': False,
    'Fast Test': False,
    }

My text file has this data:
{‘Exit’: None, ‘Start Phase’: ‘STRT’, ‘Turn Reduction’: 0, ‘Smart Focus’: False, ‘Smart Shutoff’: True, ‘Fast Test’: False}
It then prints and uses this:
{‘Start Phase’: ‘STRT’, ‘Smart Focus’: False, ‘Smart Shutoff’: True, ‘Turn Reduction’: 0, ‘Fast Test’: False, ‘Exit’: None}
Suddenly everything is in a random order, and my code relies on this dictionary being ordered.
When I take the SD card back to my computer, the contents in the file are scrambled just as it prints.
This also happens with every other evaluate command that I have that reads a file.

I tried switching my SD card to a smaller one, and I also tried changing the code. Even when the main part reads as

try:
    with open("/ROBOT2/settings.txt", 'r') as file:
        #settings = eval(file.read())
        settings = {'Exit': None}
        exec(file.read())
        print(settings)

and the file says
settings = {‘Exit’: None, ‘Start Phase’: ‘STRT’, ‘Turn Reduction’: 0, ‘Smart Focus’: False, ‘Smart Shutoff’: True, ‘Fast Test’: False,}
The effect is still the same

So, how do I fix this? Do I try another SD card? Am I reading files wrong? Does eval and exec not work well? What’s going on?

Not sure this (using eval with a file on an SD card) is even supported, certainly it has never been tested.

Is this on V5 ?

It is indeed. I’m just using python VEXcode V5.

I’ll have a look when I’m back in the office next week, but I think you are probably out of luck keeping the dict items in order.

I’ve been burned by this in using micropython. The order isn’t guaranteed, the values are hashed and it tries to reduce how much memory gets used. If the order is important then you’ll need to do something like.


ordered_settings = [
    ('Exit', None),
    ('Turn Reduction', 10),
    ('Start Phase', 'STRT'),
    ('Smart Focus', False),
    ('Smart Shutoff', False),
    ('Fast Test', False)
]

for k, v in ordered_settings:
    print(k, ":", v)

I don’t know what V5 uses, so this may be a red herring.

V5, EXP and IQ2 all use a version of micropython that’s now a few years old (AIM is more recent).

when I google what might happen, I’m told

Prior to Python 3.6:
Standard dictionaries did not guarantee any specific order; elements were returned in an arbitrary order based on the hash table implementation. For ordered dictionaries in these versions, the collections.OrderedDict class was necessary.

micropython is based on 3.4 I believe with some featires from later versions.

The OrderedDict may have been a solution, but that feature is currently not included in the V5 build, it’s a choice made when building that we did not enable, perhaps in the future we can turn that on.

Thank you so much for the idea, and you too @jpearman for the info. I fixed everything and it’s all finally working. I’m going to upload it to the robot today or very soon and fingers crossed it works.