简体   繁体   中英

Updating already existing json file python

I have a json file and I want to update 'filename' field with the filenames I scp from a remote server. I am pretty new to python but learning as I go.

JSON file:

{"path":"/home/Document/Python", 
"md5s":[{"filename":"",
    "md5":"",
    "timestamp":""},
   {"filename":"",
    "md5":"",
    "timestamp":""},
   {"filename":"",
    "md5":"",
    "timestamp":""}
]}

My python code so far:

  def filemd5():
   try:
    config = json.load(open(config_file))
    #print(str(json.dumps(config, indent=4)))
    for server in config['servers']:
            ssh = SSHClient() 
            ssh.load_system_host_keys()

            ssh.connect(server['ip'], username=server['username'], 
                        password=server['password'])
        #print(str(server)) 
        print('Connecting to servers')
        ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command('ls /tmp/')
        error = str(ssh_stderr.read())
        if len(error) ==0:
            for files in config['servers']: 
                filename = file_location + server['file']
                scp = SCPClient(ssh.get_transport())
                scp.get(filename)
            if os.path.isfile(server['file']):
                updateJsonFile(filename)
                print(filename)
            else:
                print('KO')

def updateJsonFile(filename):
        with open('md5.json', 'r') as f:
           data = json.load(f)

       subdata = data['md5s']
       for check in subdata:
           check["filename"] = filename

       with open('md5.json', 'w') as f:
           f.write(json.dumps(data))

filemd5()

Formatting has not really came out well here but I am nearly sure it is good in my python script. What is happening now is that it populates all fields 'filename' with the same file when I am SCP three files from different servers.

Any help would be great. Thanks.

EDIT(updated question as adding to file works but it fills all values with same filename.

Expected result:

{"path":"/home/Document/Python", 
 "md5s":[{"filename":"text1.txt",
"md5":"",
"timestamp":""},
{"filename":"text2.txt",
"md5":"",
"timestamp":""},
{"filename":"text3.txt",
"md5":"",
"timestamp":""}
 ]}

Actual:

 {"path":"/home/Document/Python", 
 "md5s":[{"filename":"text1.txt",
"md5":"",
"timestamp":""},
{"filename":"text1.txt",
"md5":"",
"timestamp":""},
{"filename":"text1.txt",
"md5":"",
"timestamp":""}
 ]}}

This is as close as I can come to sorting the code for you. I don't know why you get KeyError but you didn't implement a counter as suggested in the comments. Since I don't have access to config['servers'] , the counter might be in the wrong place, in which case put it in the inner for loop. I tested this on your json string and it does work as you intended so the principle is correct, you just have to make sure you pass the desired values for counter .

def filemd5():
    try:
        config = json.load(open(config_file))

        counter = 0 # Add a counter here
        for server in config['servers']:
            ssh = SSHClient() 
            ssh.load_system_host_keys()

            ssh.connect(server['ip'], username=server['username'], 
                            password=server['password'])

            print('Connecting to servers')
            ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command('ls /tmp/')
            error = str(ssh_stderr.read())
            if not error: 
                for files in config['servers']: 
                    filename = file_location + server['file']
                    scp = SCPClient(ssh.get_transport())
                    scp.get(filename)
                if os.path.isfile(server['file']):
                    updateJsonFile(filename, counter)
                    counter += 1 # increment the counter
                    print(filename)
                else:
                    print('KO')
    except:
        # I don't understand why you don't get an error for missing except?
        pass  

def updateJsonFile(filename, counter):
    with open('md5.json', 'r') as f:
        data = json.load(f)

    subdata = data['md5s']
    # The code below would update every value since you loop through whole list
    #for check in subdata:
    #   check["filename"] = filename
    subdata[counter]['filename'] = filename

    with open('md5.json', 'w') as f:
        f.write(json.dumps(data))

If I have correctly understood, you start with a json file containing a list of references to file, and you want to update the next element of the list.

You could browse the data['md5s'] searching for the first element where the filename field is empty, and add a new dictionnary to the list if all are already completed:

def updateJsonFile(filename):
    jsonFile = open("md5.json", "r")  # load data from disk
    data = json.load(jsonFile)
    jsonFile.close()

    for tmp in data["md5s"]:  # browse the list
        if len(tmp['filename']) == 0:  # found one empty slot, use it and exit looop
            tmp['filename'] = filename
            break
    else:     # no empty slot found: add a new dict
        data["md5s"].append({'md5': '', 'timestamp': '', 'filename': filename})
    jsonFile = open("m.json", "w")  # write the json back to file
    json.dump(data, jsonFile)
    jsonFile.close()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM