无法在Mac/Linux上加载Pickled文件

5 投票
5 回答
12116 浏览
提问于 2025-04-11 18:14

我有一个应用程序,它可以从一个叫做“pickled file”的文件中导入数据。在Windows上运行得很好,但在Mac和Linux上就有点奇怪。

在OS X上,扩展名为“.char”的pickled文件在选择时是不可见的,除非我把文件类型设置为*.*。然后,如果我选择一个扩展名为.char的文件,它就无法加载,还会报错:

unpickle_file = cPickle.load(char_file) 

ValueError: 无法将字符串转换为浮点数

不过,如果我创建一个没有.char扩展名的文件,那这个文件就能正常加载。

在Linux上,当我使用“打开文件”对话框时,我的pickled文件无论有没有扩展名都看不见。不过,我可以在Nautilus或Dolphin中看到它们,但在我的应用程序里它们就是不存在。


编辑 这是保存文件的代码:

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()

这是打开文件的代码:

 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()

5 个回答

4

出现这个错误的另一个原因是忘记在保存数据后关闭输出文件。这会导致文件不完整,在之后读取数据时可能会出现各种意外的问题。

9

正如Adam提到的,问题可能出在pickle文件的换行格式上。

不幸的是,真正的问题其实是在保存的时候,而不是加载的时候。如果你使用的是文本模式的pickle文件,而不是二进制模式,可能还有恢复的机会。你可以尝试以通用换行模式打开文件,这样Python会自动判断正确的行结束符,比如:

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

不过,如果你使用的是二进制格式(比如cPickle.dump(file, 1)),那么你可能会遇到无法恢复的损坏pickle文件(即使在Windows上加载时也会出现问题)。如果运气好,没有出现\r\n字符,可能还会正常工作,但一旦出现这些字符,你的数据就可能损坏,因为没有办法区分“真实”的\r\n代码和Windows在看到\n时插入的字符。

为了确保在多个平台上都能正常加载,最好的做法是始终以二进制模式保存。在你的Windows机器上,保存pickle时使用:

char_file = open('filename.char','wb')
cPickle.dumps(data, char_file)
10

可能是你在写入或读取被“腌制”的数据时,没有以二进制模式打开文件。在这种情况下,换行符的格式会被转换,这可能会导致二进制数据损坏。

要以二进制模式打开文件,你需要在模式字符串中加上“b”:

char_file = open('pickle.char', 'rb')

撰写回答