Skip to content
Advertisement

Adding and saving to list in external json file

I’m very new to Python and I’m struggling when it comes to saving the data that the user has entered to a json file when quitting the application. Also every time I run my code all the data inside the json file is wiped. When I enter the input to save and exit I get this error code:

Traceback (most recent call last):
  File "C:UsersUserDownloadssit_resourcessit_resourcessit_admin_application.py", line 86, in <module>
    main_menu()
  File "C:UsersUserDownloadssit_resourcessit_resourcessit_admin_application.py", line 23, in main_menu
    save()
  File "C:UsersUserDownloadssit_resourcessit_resourcessit_admin_application.py", line 82, in save
    patients_file.write(finallist)
io.UnsupportedOperation: not writable

Here is my code below:

import json
patients_file = open("patients.json", "r")
loaded_patients = json.load(patients_file)

def main_menu():
    '''Function docstring documentation here'''
    print("nSIT Data Entry Menu")
    print("==========================")
    print("1: Print Patients' Listn2: Add Patientn3: Delete Patientn4: Exit")
    print("==========================")
    input1 = input("Enter your menu selection:")
    if input1 == "1":
        patients_list()
    elif input1 == "2":
        add_patient()
    elif input1 == "3":
        remove_patient()
    elif input1 == "4":
        save()
    else:
        print ("Please enter a valid input")
        main_menu()

def patients_list():
    print("nSIT current patients:n")
    loaded_patients.sort(key=str.casefold)
    for number, item in enumerate(loaded_patients, start=1):
        print(number, item)
    print("nTotal number of registered patients is", len(loaded_patients))
    main_menu()

def add_patient():
    newpatient = input("nEnter new Patient -> Lastname Firstname:")
    print ("Do the details you have entered look correct? y/n")
    confirm = input()
    if confirm == "y":
        loaded_patients.append(newpatient)
        print ("Patient successfully added to list")
        main_menu()
    elif confirm == "n":
        print ("Patient import cancelled")
        add_patient()
    else:
        print ("Please enter a valid input")
        add_patient()

def remove_patient():
    print ("Which of the following patients would you like to remove?")
    loaded_patients.sort(key=str.casefold)
    for number, item in enumerate(loaded_patients, start=1):
        print(number, item)
    try:
        removepatient = int(input("nEnter the number of the patient you would like to remove"))
        print ("Does the patient number you have entered look correct? y/n")
        delconfirm = input()
        if delconfirm == "y":
            try:
                removepatient = (removepatient - 1)
                loaded_patients.pop(removepatient)
                print ("Patient was successfully removed from the list")
                main_menu()
            except IndexError:
                print("Please enter a valid input")
                remove_patient()
        elif delconfirm == "n":
            print ("Deletion cancelled")
            remove_patient()
        else:
            print ("Please enter a valid input")
            remove_patient()
    except ValueError:
        print ("Please enter a valid input")
        remove_patient()

def save():
    open("patients.json", "w")
    finallist = json.dumps(loaded_patients)
    patients_file.write(finallist)
    print("Patient List successfully saved")
    quit()

main_menu()

I store the json file in the same directory and all it contains is a list:

["Soreback Leigh", "Neckache Annette", "Sorefoot Jo", "Kaputknee Matt", "Brokentoe Susan", "Tornligament Alex"]

If anyone could help me out and let me know what I’m doing wrong or any simpler method I could use, it would be greatly appreciated. Thanks

Advertisement

Answer

Your code has several issues, including the one you’re asking about.

The main thing is the overall structure: your code keeps calling functions from functions, never really returning – that can work for a very long time, but in the end it will fail, and it’s not the correct way to go about this.

Take for example your main_menu() – once an option is selected, you call the function matching it, and when the work there is done, you call main_menu() again. However, a better way to do the same:

def main_menu():
    choice = ''
    while choice != '4':
        print('some options, 4 being "save and quit"')
        if choice == 1:
            patients_list()
        ...
        # no if choice == 4: save() here, we'll save at the end
    save()

This way, the menu will keep getting printed when you return to it, but every function that is executed, is allowed to return and then the loop restarts, unless option 4 was entered. And since you can allow the functions to return, no need to call main_menu() at the end of them.

Your save() function has some issues: it doesn’t need quit() any more, but you also didn’t do anything with the file you opened. A nice way to do this in Python is to use a ‘context manager’, which boils down to using with, like this:

def save():
    with open("patients.json", "w") as patients_file:
        finallist = json.dumps(loaded_patients)
        patients_file.write(finallist)

That’s assuming your loaded_patients always contains all the current patients of course. Given that’s what it is for, you should consider just calling it patients.

Your file only contains a list, because a list is what you are creating in those functions and a list is a valid content for a json file. If you expected a dictionary, you should construct one in the rest of the code, but from your example it’s unclear what exactly you would expect that dictionary to look like.

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement