Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AttributeError while unpickling: Can't get attribute 'Location'

Tags:

python

cgi

I'm writing a Python CGI script for an inventory system. It needs to store through pickle a list (called locations) of objects. Here's the code I'm using:

try:
    with open(".config/autosave.bin", "rb") as dataFile:
        locations = pickle.load(dataFile)
except (FileNotFoundError, PermissionError):
    dispHTML("p", contents="Error in load:  Save file incorrectly configured!")
    locations = []

However, this results in:

 /Applications/MAMP/cgi-bin/ic/main.py in ()
     16 try:
     17         with open(".config/autosave.bin", "rb") as dataFile:
=>   18                 locations = pickle.load(dataFile)
     19 except (FileNotFoundError, PermissionError):
     20         dispHTML("p", contents="Error in load:  Save file incorrectly configured!")
AttributeError: Can't get attribute 'Location' on <module '__main__' from '/Applications/MAMP/cgi-bin/ic/main.py'> 
      args = ("Can't get attribute 'Location' on <module '__main__' from '/Applications/MAMP/cgi-bin/ic/main.py'>",) 
      with_traceback = <built-in method with_traceback of AttributeError object>

As you can see the save file is stored at .config/autosave.bin. Writing to it seems to work fine but I haven't been able to check.

How can I fix this?


1 Answers

The pickle reading code requires the definition of the Location class. If not it will not be able to reconstruct custom objects of that class.

# config_writer.py

import pickle

class Location:
    def __init__(self, store, aisle):
        self.store = store
        self.aisle = aisle

locations = [Location(i, i) for i in range(10)]
with open('.config/autosave.bin', 'wb') as f:
    pickle.dump(locations, f)

Here is a example that tries to read the pickle file without having the class definition of Location (run this code in another terminal/session):

>>> import pickle
>>> with open('.config/autosave.bin','rb') as f:
...     data = pickle.load(f)
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
AttributeError: Can't get attribute 'Location' on <module '__main__' (built-in)>

However, with access to the class definition:

>>> from config_writer import Location
>>> with open('.config/autosave.bin','rb') as f:
...     data = pickle.load(f)
>>> data
[<config_writer.Location object at 0x7f8b472111d0>, <config_writer.Location object at 0x7f8b41ad6e48>, <config_writer.Location object at 0x7f8b41adb0f0>, <config_writer.Location object at 0x7f8b41adb128>, <config_writer.Location object at 0x7f8b41adb160>, <config_writer.Location object at 0x7f8b41adb198>, <config_writer.Location object at 0x7f8b41adb1d0>, <config_writer.Location object at 0x7f8b41adb208>, <config_writer.Location object at 0x7f8b41adb240>, <config_writer.Location object at 0x7f8b41adb278>]

Hopefully the code that reads the pickle file is able to import the class definition for Location from some other module as does my example.

like image 57
mhawke Avatar answered Feb 07 '26 07:02

mhawke