Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 3.3 Pickle Errors for read/write

I'm trying to write a program that displays a menu and allows users to write to a file, read from a file, or exit. The file contains a list object, so I'm using a .dat file. I've read the python documentation and loads of 'pickle error' threads on this site, but can't seem to understand why I'm getting the errors I'm getting. I'd love any insight!

Error for write_to_file function:

integer is required

As far as I can tell, I'm using the correct form of open, which seemed to be what was giving other users trouble with this error, and I can't find anything in the Python documentation about a required integer argument to pickle.dump (Also, I'm pretty sure the method I'm using to allow the user to input data to the file is incorrect, but I haven't been able to get past the pickle errors preceding it.)

def write_to_file():
    s = open('studentInfo.dat')
    pickle.dump(info, s, 'wb')
    shelve.open(s)
    print(s)
    print("You may now add information to the file:")
    input(s[''])
    s.close()

Error for read_file function:

io.UnsupportedOperation: write

I have no 'w' or 'wb' arguments in this function, and I want it to be a read-only action anyway. Where is the write error hidden?

def read_file():
    f = open('studentInfo.dat', 'rb')
    pickle.dump(info, f)
    shelve.open(f, 'rb')
    print("Here is the student information: \n")
    print(f)
    f.close()

Here's the full code:

#import necessary modules:
import pickle, shelve

# create list object
info = [[("student", "John"),("GPA","4.0"), ("ID", "01234")],
        [("student", "Harry"),("GPA","3.2"), ("ID", "03456")],
        [("student", "Melissa"),("GPA","1.8"), ("ID", "05678")],
        [("student", "Mary"),("GPA","3.5"), ("ID", "07899")]]

#Function Definitions
def write_to_file():
    s = open('studentInfo.dat')
    pickle.dump(info, s, 'wb')
    shelve.open(s)
    print(s)
    print("You may now add information to the file:")
    input(s[''])
    s.close()

def read_file():
    f = open('studentInfo.dat', 'rb')
    pickle.dump(info, f)
    shelve.open(f, 'rb')
    print("Here is the student information: \n")
    print(f)
    f.close()

#def main(): #while loop as program engine, constantly prompt user, display menu, etc.

menu = ("\n0 - Exit the Program",               #Exit
        "\n1 - Add student information",        #Write to file
        "\n2 - Print student information")  #Read file

print(menu)
menuchoice = int(input("Please enter a number that matches the menu option you want: "))
##writetofile = open("studentInfo.dat", "wb")
##printinfo = open("studentInfo.dat", "rb")

if menuchoice == 0:
    input("\nPress the 'enter' key to exit the program.")
elif menuchoice == 1:
    print("You may add a student, gpa, or student ID to the file")
    write_to_file()
elif menuchoice == 2:
    read_file()
like image 427
Jim Avatar asked Aug 03 '26 21:08

Jim


1 Answers

You need to pass the mode parameter to the open() call, not to pickle.dump():

s = open('studentInfo.dat', 'wb')
pickle.dump(info, s)

To load from an open file, use pickle.load():

f = open('studentInfo.dat', 'rb')
info = pickle.load(f)

You don't need the shelve module and calls here at all. Remove those.

You probably want to use the files as context managers here, closing them automatically:

with open('studentInfo.dat', 'wb') as outputfile:
    pickle.dump(info, outputfile)

and

with open('studentInfo.dat', 'rb') as inputfile:
    info = pickle.load(inputfile)

You cannot add just add unstructured additional information to the file after opening; add the new information to info before pickling info to the file:

def write_to_file():
    # take input and add that to `info` here.
    # gather a name, GPA and ID into `new_name`, `new_gpa` and `new_id`
    info.append([("student", new_name),("GPA", new_gpa), ("ID", new_id)])

    with open('studentInfo.dat', 'wb') as outputfile:
        pickle.dump(info, outputfile)

Your read_file() function should probably return the read information, or you should make info an explicit global:

def read_file():
    with open('studentInfo.dat', 'rb') as inputfile:
        info = pickle.load(inputfile)
    return info

By returning from the function, you can then assign it back to info or print it:

read_info = read_file()
print("Here is the student information: \n")
print(read_info)
like image 54
Martijn Pieters Avatar answered Aug 06 '26 10:08

Martijn Pieters



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!