【问题标题】:Pickled file won't load on Mac/Linux腌制文件不会在 Mac/Linux 上加载
【发布时间】:2014-07-24 09:12:01
【问题描述】:

我有一个从腌制文件导入数据的应用程序。它在 Windows 中运行良好,但 Mac 和 Linux 的行为很奇怪。

在 OS X 中,除非我将文件类型设置为 *.*,否则无法选择腌制文件(文件扩展名“.char”)。然后,如果我选择一个具有 .char 扩展名的文件,它将无法加载,并给出错误

unpickle_file = cPickle.load(char_file) 

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

但是,如果我创建一个没有 .char 扩展名的文件,该文件将正常加载。

在 Linux 中,当我使用“文件打开”对话框时,我的腌制文件不可见,无论它们是否具有文件扩展名。但是,我可以在 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()

【问题讨论】:

标签: python linux macos cross-platform


【解决方案1】:

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

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

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

【讨论】:

  • 我认为这不会有帮助,因为在 linux 文本模式下无论如何都与二进制相同。 \r 已经存在,所以这个问题确实需要在保存时解决(尽管在通用换行模式下打开可能会解决它。)
  • 既然公开内容已经发布,请随意将“可能”更改为“肯定”。
【解决方案2】:

Adam提到的问题很可能是pickle文件的换行格式。

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

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

但是,如果您使用的是二进制格式 (cPickle.dump(file, 1)),您可能会遇到不可恢复的损坏 pickle(即使在 Windows 中加载时也是如此) - 如果您很幸运并且没有 \r\n 字符出现然后它可能会起作用,但是一旦发生这种情况,您最终可能会收到损坏的数据,因为没有办法区分“真实”\r\n 代码和仅看到 \n 时插入的一个窗口。

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:
      self.file = open(self.file_name, 'w')

      应该是:

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

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

      如果您不使用二进制模式,那么 Windows 会将所有换行符转换为 \r\n 并有效地损坏文件(至少就其他操作系统而言)。

      【讨论】:

        【解决方案5】:

        使用dos2unix工具

        dos2unix pickle.char
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-17
          • 1970-01-01
          • 1970-01-01
          • 2017-03-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多