Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pickled file won't load on Mac/Linux

I have an application that imports data from a pickled file. It works just fine in Windows but Mac and Linux behaviour is odd.

In OS X, the pickled file (file extension ".char") is unavailable as a selection unless I set the file type to *.*. Then, if I select a file that has the .char extension, it won't load, giving the error

unpickle_file = cPickle.load(char_file) 

ValueError: could not convert string to float

However, if I create a file that doesn't have the .char extension, that file will load up just fine.

In Linux, when I use the "file open" dialog, my pickled files aren't visible, whether or not they have a file extension. However, I can see them under Nautilus or Dolphin. They simply don't exist to my application though.


Edit Here's the save code:

def createSaveFile(self):
        """Create the data files to be saved and save them.

        Creates a tuple comprised of a dictionary of general character information
        and the character's skills dictionary."""
        if self.file_name:
            self.save_data = ({'Name':self.charAttribs.name,

              <snip> 

                self.charAttribs.char_skills_dict)
            self.file = open(self.file_name, 'w')
            cPickle.dump(self.save_data, self.file)
        self.file.close()

Here's the open code:

 def getCharFile(self, event): # wxGlade: CharSheet.<event_handler>
        """Retrieve pickled character file from disk."""
        wildcard = "Character files (*.char) | *.char | All files (*.*) | *.*"        
        openDialog = wx.FileDialog(None, "Choose a character file", os.getcwd(),
        "", wildcard, wx.OPEN | wx.CHANGE_DIR)
        if openDialog.ShowModal() == wx.ID_OK:
            self.path = openDialog.GetPath()
        try:
            char_file =  open(self.path, "r")
            unpickle_file = cPickle.load(char_file)
            char_data, char_skills = unpickle_file
            self.displayCharacter(char_data, char_skills)
        except IOError:
            self.importError = wx.MessageDialog(self, 
            "The character file is not available!",
            "Character Import Error", wx.OK | wx.ICON_ERROR)
            self.importError.ShowModal()
            self.importError.Destroy()
            openDialog.Destroy()
like image 561
crystalattice Avatar asked Nov 12 '08 12:11

crystalattice


2 Answers

Probably you didn't open the file in binary mode when writing and/or reading the pickled data. In this case newline format conversion will occur, which can break the binary data.

To open a file in binary mode you have to provide "b" as part of the mode string:

char_file = open('pickle.char', 'rb')
like image 195
Adam Byrtek Avatar answered Oct 09 '22 19:10

Adam Byrtek


As mentioned by Adam, the problem is likely to be the newline format of the pickle file.

Unfortunately, the real problem is actually caused on save rather than load. This may be recoverable if you're using text mode pickles, rather than binary. Try opening the file in universal newline mode, which will cause python to guess what the right line-endings are ie:

char_file=open('filename.char','rU')

However, if you're using a binary format (cPickle.dump(file, 1)) you may have an unrecoverably corrupted pickle (even when loading in Windows) - if you're lucky and no \r\n characters show up then it may work, but as soon as this occurs you could end up with corrupted data, as there's no way to distinguish between a "real" \r\n code and one windows has inserted on seeing just \n.

The best way to handle things to be loaded in multiple platforms is to always save in binary mode. On your windows machine, when saving the pickle use:

char_file = open('filename.char','wb')
cPickle.dumps(data, char_file)
like image 22
Brian Avatar answered Oct 09 '22 17:10

Brian