代码之家  ›  专栏  ›  技术社区  ›  crystalattice

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

  •  5
  • crystalattice  · 技术社区  · 16 年前

    我有一个从pickled文件导入数据的应用程序。它在Windows中工作得很好,但是Mac和Linux的行为很奇怪。

    在OS X中,除非将文件类型设置为*.*,否则pickled文件(文件扩展名“.char”)不能作为选择。然后,如果我选择一个扩展名为.char的文件,它将不会加载,并给出错误信息

    unpickle_file = cPickle.load(char_file) 
    

    ValueError:无法将字符串转换为float

    但是,如果我创建一个没有.char扩展名的文件,那么这个文件就可以加载了。

    在Linux中,当我使用“文件打开”对话框时,不管是否有文件扩展名,我的pickled文件都不可见。不过,我可以在鹦鹉螺或海豚下面看到它们。不过,它们在我的应用程序中根本不存在。


    编辑 以下是保存代码:

    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 回复  |  直到 10 年前
        1
  •  10
  •   Adam Byrtek    16 年前

    在写入和/或读取pickled数据时,可能没有以二进制模式打开文件。在这种情况下,将发生换行格式转换,这可能会破坏二进制数据。

    要以二进制模式打开文件,必须提供“b”作为模式字符串的一部分:

    char_file = open('pickle.char', 'rb')
    
        2
  •  8
  •   Community CDub    7 年前

    如上所述 Adam ,问题可能是pickle文件的换行格式。

    不幸的是,真正的问题实际上是由 节约 而不是装载。如果您使用的是文本模式pickles,而不是二进制文件,那么这可能是可恢复的。尝试以通用换行模式打开文件,这将导致python猜测正确的行尾是什么,即:

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

    但是,如果您使用的是二进制格式(cpickle.dump(file,1)),则可能存在无法恢复的损坏pickle(即使在Windows中加载时也是如此)-如果您很幸运并且没有显示\r\n字符,则它可能会工作,但一旦发生这种情况,您可能会以损坏的数据结束,因为无法区分“real”代码和一个窗口s已插入“仅查看”命令\n。

    处理要在多个平台中加载的内容的最佳方法是始终以二进制模式保存。在Windows计算机上,保存pickle时使用:

    char_file = open('filename.char','wb')
    cPickle.dumps(data, char_file)
    
        3
  •  4
  •   jkellydresser    13 年前

    另一种获得此错误的方法是忘记在酸洗后关闭输出文件。这可能会留下一个不完整的文件,在随后的解压过程中以随机方式失败。

        4
  •  2
  •   John Montgomery    16 年前
    self.file = open(self.file_name, 'w')

    应该是:

    self.file = open(self.file_name, 'wb')

    在你 createSaveFile 函数,以二进制模式(而不是文本模式)保存文件。您还应该确保以二进制模式打开文件(rb)。

    如果不使用二进制模式,则Windows会将所有新行转换为\r\n并有效地损坏文件(至少在其他操作系统中如此)。

        5
  •  0
  •   Hadi    10 年前

    使用dos2unix工具

    dos2unix pickle.char