Python Forum

Full Version: error creating new object after loading pickled objects from file
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi All,

I am brand new to Python and am having good success so far, but I am stuck. I created a class and a Tkinter form to accept input and add objects to the class and then save the objects to a list and save them out to a pickle file. I am able to then import them again so my list is persistent, but when I try to add another Thing object after I import the previous data I get a "TypeError: 'Thing' object is not callable" error. I'm not sure what is happening since I can add as many new objects and put them in a list as I want without error, and I can then save and then import the pickled list fine, but I get the error only when I try to add a new object after I import the pickled list. I am using 3.7.

The code below works fine until I unremark the section of code right below the class definition. This is the section of code that imports the pickled data from the file. My print statements show that the data is pickling and unpickling fine. I'm wondering of the problem has something to do with a mismatch between what I'm pickling and unpickling (a "Things" list of "Thing" objects) versus what I'm then adding (a "Thing" object) after I import the pickled data. I get the error at the "x = Thing(nameEntry.get(), descriptionEntry.get())" line.

from tkinter import *
import pickle

Things = []
print('this next line will show the empty list of Thing objects:')
print(Things)


class Thing(object):
    def __init__(self, name, description):
        self.name = name
        self.description = description
        Things.append(self)


"""
# open file and assign Thing objects in saved file to Things list
with open('Things.pkl', 'rb') as input:
    Things = pickle.load(input)

# print(Things)   # this should print all Things brought in from file
print('this next section should show the name and description for each Thing in the Things list of Thing'
      ' objects read from the file when this app is first run, before we add any new Things')
for Thing in Things:
    print(Thing.name, Thing.description)
"""


def lftclick(event):
    x = Thing(nameEntry.get(), descriptionEntry.get())
    print('this next line will show the Thing object we just created:')
    print(x)


MainWindow = Tk()
# create 2 labels, 2 entry, and a button widgets
nameLabel = Label(MainWindow, text="Name")
nameEntry = Entry(MainWindow)
descriptionLabel = Label(MainWindow, text="Description")
descriptionEntry = Entry(MainWindow)
addButton = Button(MainWindow, text="Save Thing", foreground="red")
# position the widgets in rows and columns
nameLabel.grid(row=1, sticky=E)
descriptionLabel.grid(row=2, sticky=E)
nameEntry.grid(row=1, column=1)
descriptionEntry.grid(row=2, column=1)
addButton.grid(row=3, columnspan=2)
# bind the left click event for the button to the lftclick event
addButton.bind("<Button-1>", lftclick)
MainWindow.mainloop()


with open('Things.pkl', 'wb') as output:
    pickle.dump(Things, output)
Thanks to the Moderator for instructing me on the proper methods of posting. Hopefully I've done it correctly this time:

I am brand new to Python and am having good success so far, but I am stuck. I created a class and a Tkinter form to accept input and add objects to the class and then save the objects to a list and save them out to a pickle file. I am able to then import them again so my list is persistent, but when I try to add another Thing object after I import the previous data I get a "TypeError: 'Thing' object is not callable" error. I am using 3.7.

The code in the FIRST SECTION below works fine. When you run it just put, say, "1" in each of the two fields on the Tkinter form and click "Save Thing". Then enter "2" in the two fields and click again and you will have created two objects.

The code in the SECOND SECTION BELOW is where the error occurs. This section shows the code I added below the Thing class definition and the "def lftclick(event)", which is the code intended to load the data from the pickled file. You'll see that the data loads fine, but when the Tkinter form comes up and you add, say, "3" into each of the two fields and click the "Save Thing" button, the error will then occur.

The THIRD SECTION below shows the actual error that occurs.

I'm wondering of the problem has something to do with a mismatch between what I'm pickling and unpickling (a "Things" list of "Thing" objects) versus the object I'm then trying to create (a "Thing" object) after I import the pickled data. I first error occurs at the "x = Thing(nameEntry.get(), descriptionEntry.get())" line.

from tkinter import *
import pickle

Things = []
print('this next line will show the empty list of Thing objects:')
print(Things)


class Thing(object):
    def __init__(self, name, description):
        self.name = name
        self.description = description
        Things.append(self)


def lftclick(event):
    x = Thing(nameEntry.get(), descriptionEntry.get())
    print('this next line will show the Thing object we just created:')
    print(x)


MainWindow = Tk()
# create 2 labels, 2 entry, and a button widgets
nameLabel = Label(MainWindow, text="Name")
nameEntry = Entry(MainWindow)
descriptionLabel = Label(MainWindow, text="Description")
descriptionEntry = Entry(MainWindow)
addButton = Button(MainWindow, text="Save Thing", foreground="red")
# position the widgets in rows and columns
nameLabel.grid(row=1, sticky=E)
descriptionLabel.grid(row=2, sticky=E)
nameEntry.grid(row=1, column=1)
descriptionEntry.grid(row=2, column=1)
addButton.grid(row=3, columnspan=2)
# bind the left click event for the button to the lftclick event
addButton.bind("<Button-1>", lftclick)
MainWindow.mainloop()


with open('Things.pkl', 'wb') as output:
    pickle.dump(Things, output)
from tkinter import *
import pickle

Things = []
print('this next line will show the empty list of Thing objects:')
print(Things)


class Thing(object):
    def __init__(self, name, description):
        self.name = name
        self.description = description
        Things.append(self)



# open file and assign Thing objects in saved file to Things list
with open('Things.pkl', 'rb') as input:
    Things = pickle.load(input)

# print all data imported from the pickled file
print('this next section will show the name and description for each Thing in the Things list of Thing'
      ' objects read from the file when this app is first run, before we add any new Things:')
for Thing in Things:
    print(Thing.name, Thing.description)



def lftclick(event):
    x = Thing(nameEntry.get(), descriptionEntry.get())
    print('this next line will show the Thing object we just created:')
    print(x)


MainWindow = Tk()
# create 2 labels, 2 entry, and a button widgets
nameLabel = Label(MainWindow, text="Name")
nameEntry = Entry(MainWindow)
descriptionLabel = Label(MainWindow, text="Description")
descriptionEntry = Entry(MainWindow)
addButton = Button(MainWindow, text="Save Thing", foreground="red")
# position the widgets in rows and columns
nameLabel.grid(row=1, sticky=E)
descriptionLabel.grid(row=2, sticky=E)
nameEntry.grid(row=1, column=1)
descriptionEntry.grid(row=2, column=1)
addButton.grid(row=3, columnspan=2)
# bind the left click event for the button to the lftclick event
addButton.bind("<Button-1>", lftclick)
MainWindow.mainloop()


with open('Things.pkl', 'wb') as output:
    pickle.dump(Things, output)
Error:
"D:\Programming\Python Projects\giraffe\venv\Scripts\python.exe" "D:/Programming/Python Projects/giraffe/delicatestopost.py" this next line will show the empty list of Thing objects: [] this next section will show the name and description for each Thing in the Things list of Thing objects read from the file when this app is first run, before we add any new Things: 1 1 2 2 Exception in Tkinter callback Traceback (most recent call last): File "C:\Users\shelly\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 1705, in __call__ return self.func(*args) File "D:/Programming/Python Projects/giraffe/delicatestopost.py", line 38, in lftclick x = Thing(nameEntry.get(), descriptionEntry.get()) TypeError: 'Thing' object is not callable Traceback (most recent call last): File "D:/Programming/Python Projects/giraffe/delicatestopost.py", line 62, in <module> pickle.dump(Things, output) _pickle.PicklingError: Can't pickle <class '__main__.Thing'>: it's not the same object as __main__.Thing Process finished with exit code 1