A problem about using pickle module

Posted by Hairui on Mon 04 Jun 2007 11:38 AM — 5 posts, 24,318 views.

China #0
To save the map information of a MUD, I tried to use pickle module of Python. The following script shows how I did that:

strWorldMapFile = r"c:\WorldMap.fy"

def LoadWorldMap():
    import pickle
    try:
        dbfile = open(strWorldMapFile)
    except:
        world.note("Can not find world map file")
        mapWrold = Map()
    else:
        mapWorld = pickle.load(dbfile)
        dbfile.close()
        world.note("World Map loaded from %s." % strWorldMapFile)
    
def SaveWorldMap():
    import pickle
    try:
        dbfile = open(strWorldMapFile,"w+")
    except:
        world.note("Can not find world map file to write")
    else:
        pickle.dump(mapWorld,dbfile)
        dbfile.close()
        world.note("World Map saved in %s ." % strWorldMapFile)

Map() is a class I defined before these codes.
But when I assign the function LoadWorldMap() to MushClient's world open event, the Mushclient show the following infomation:

Script error
World: FY4Local
Execution of line 101 column 0
Function/Sub: OnWorldOpen called by world open
Reason: opening world
Traceback (most recent call last):
  File "<Script Block >", line 13, in OnWorldOpen
    LoadWorldMap()
  File "<Script Block >", line 101, in LoadWorldMap
    mapWorld = pickle.load(dbfile)
  File "C:\Python25\Lib\pickle.py", line 1370, in load
    return Unpickler(file).load()
  File "C:\Python25\Lib\pickle.py", line 858, in load
    dispatch[key](self)
  File "C:\Python25\Lib\pickle.py", line 1069, in load_inst
    klass = self.find_class(module, name)
  File "C:\Python25\Lib\pickle.py", line 1124, in find_class
    __import__(module)
ImportError: No module named __ax_main__



I wrote some similar code and run it on Python Interactive windows, it works well. So I think the problem is that the __name__ of the MushClient's Python environment is "__ax__main__", but not the "__main__" of the "Pure" python environment.

Does anybody have the idea to solute the problem?
Amended on Mon 04 Jun 2007 11:56 AM by Hairui
China #1
By the way, I assigned the function SaveWorldMap to MushClient's World Save event and it seemed to work well.
Russia #2
It looks like you are trying to unpickle a class that is defined in Mushclient's script file, and the pickler tries to import the source of that class as a module.

Try dumping the Map class into a pure Python object (a dict, for example) when pickling it, and instantiating that class from the dict when loading. That would remove the need to load the class definition when unpickling.
China #3

Thanks for Ked's reply.

I am trying to solute the problem by override the Unpickler class's some methods. If I got some goode idea I will post it here soon.
China #4
Finally I have found some methods to solute the problem.
I wrote the following codes to override the original Unpickler class.

import pickle

class axUnpickler(pickle.Unpickler):
    def find_class(self, module, name):
        # Subclasses may override this
        #module = "__main__"
        if module != "__ax_main__":
            __import__(module)
            mod = sys.modules[module]
            klass = getattr(mod, name)
        else:
            klass = eval(name)
        
        return klass
    
def axUnpicklerLoad(file):
    return axUnpickler(file).load()


After replacing the pickle.load() method with axUnpicklerLoad(), all seem to work well.