issue with json file/ json compatible dictionary being implicitly edited

the code i have is for a basic sockets rock paper scissors game, it uses a request based system to ask the server to do things and I’ve used json files to organize this. it stores a blank json file of the request format so that once the changes to the game have been made the request file can be put back to the default of not making any request. for some reason this file is getting edited despite not being explicitly edited.

i have no clue why this is happening as the "blank_request_jdict" variable isn’t even used in the code which edits it. this is only a small chunk of the full code but its the part with the error somewhere within it.

here is the minimized code with the error – added print statements to show what’s going on

import json

requests_jstring = """{
    "request":{
        "null_request": {
            "active":0
        },
        "setup_new_room": {
            "active":0
        },
        "pick": {
            "active":0,
            "option":"rock"
        },
        "resign": {
            "active":0
        },
        "join_existing_room": {
            "active":0,
            "roomID": 0
        }
    }
}"""
blank_request_jdict = json.loads(requests_jstring)
request_jdict = blank_request_jdict

print("this is what blank requests should be\n", blank_request_jdict)
print("")
print("notice after 'active' every value is 0")
print("")

def request_packer(request_name = "null_request",
                   arg_1=0,
                   arg_2="0,0",
                   arg_3=0,
                   request_jdict = ""):
    """this adds the requests to the request_jdict to then be sent to the server"""
    arg_0=1
    arguments = [arg_0, arg_1, arg_2, arg_3]
    if request_name in request_jdict["request"].keys():
        print("request_name:'",request_name,"' detected - adding to request")
        argnum = 0
        for key in request_jdict["request"][request_name].keys():
            request_jdict["request"][request_name][key]=arguments[argnum]
            argnum = argnum +1
    return request_jdict

request_jdict = request_packer("setup_new_room",request_jdict = request_jdict)

print("but blank jdict is\n", blank_request_jdict)
print("")
print("this blank jdict should never be changed by the code",
      "\nand yet the 'setup new room' 'active' key is edited to 1")


>Solution :

>>> import copy
>>> import json
>>>
>>> blank_request_jdict = json.loads('{"foo": "bar"}')
>>> request_jdict = blank_request_jdict
>>>
>>> print(f"id(request_jdict): {id(request_jdict)}")
id(request_jdict): 4417488128
>>> print(f"id(blank_request_jdict): {id(blank_request_jdict)}")
id(blank_request_jdict): 4417488128
>>>
>>> request_jdict_copy = copy.deepcopy(request_jdict)
>>> print(f"id(request_jdict_copy): {id(request_jdict_copy)}")
id(request_jdict_copy): 4415526208

request_jdict and request_jdict are the same thing. There’s a few ways to copy objects in python3, but if you only remember one, copy.deepcopy() is the one that with the least surprises.

Leave a Reply