【问题标题】:python read class data member from a filepython从文件中读取类数据成员
【发布时间】:2016-06-16 17:42:10
【问题描述】:

我是 python 新手,所以我不知道一些基本的东西。我有一个包含对象数组的二进制文件。存储的对象是传统的 C 结构。我想在 python 中重新创建该结构并在其对象列表中读取文件内容,对数据进行一些修改并将其存储回来。我遇到问题的部分是读取文件内容。我读过一些关于阅读文件的类似问题,但他们没有回答我的问题。我试过用__slot__定义类和定义类成员 并使用pickle 读取数据,但效果不佳。此外,其中一个数据成员实际上是一个包含不同结构对象的数组也可能是相关的。阅读此文件的最佳方式是什么?

【问题讨论】:

    标签: python-2.7 file


    【解决方案1】:

    您需要使用 python 的struct.unpack()。您需要准确地知道它们是什么类型,以及它们是如何打包在磁盘上的。 pickle 特定于 Python 的存储格式,对你没有任何用处,除非你将序列化转换为特定于 python 的东西。

    我最近回答了一个模糊相似的问题here,它展示了如何在文件中使用mmap(),您可能会发现它比os.read() 更方便

    我可能会首先创建一个具有构造函数的类,您可以在其中使用文件指针、mmap 对象和偏移量的某种组合对其进行初始化。

    然后__init___() 方法将读取并使用结构的解压缩内容初始化self 的属性。然后添加访问器方法来修改这些属性,然后使用struct.packmmap()os.write 将它们全部写回save() 方法

    以下是 Python 文档中打包和解包三个整数(2 个 16 位短,后跟一个 32 位长)的示例:

    >>> from struct import *
    >>> pack('=hhl', 1, 2, 3)
    '\x00\x01\x00\x02\x00\x00\x00\x03'
    >>> unpack('=hhl', '\x00\x01\x00\x02\x00\x00\x00\x03')
    (1, 2, 3)
    >>> calcsize('hhl')
    8
    

    听起来您的数据可能是可变长度的……这意味着您可能无法就地修改数据。

    这是一个使用os.read()mmap 的Python2 示例。我用dd if=/dev/zero of=/tmp/three_numbers.dat count=1 bs=1k预先创建了/tmp/three_numbers.dat

    import mmap
    import os
    import struct
    
    
    class ThreeNumbers(object):
    
        PACK = '=hhl'
        SIZEOF = struct.calcsize(PACK)
    
        def __init__(self, fd, offset):
            self._fd = fd
            self._offset = offset
            self._fd.seek(offset * self.SIZEOF)
            self._data = os.read(fd.fileno(), self.SIZEOF)
            self.numbers = struct.unpack(self.PACK, self._data)
    
        def save(self):
            self._fd.seek(self._offset * self.SIZEOF)
            os.write(self._fd.fileno(), struct.pack(self.PACK, *self.numbers))
    
    
    class ThreeNumbersMMAP(object):
    
        PACK = '=hhl'
        SIZEOF = struct.calcsize(PACK)
    
        def __init__(self, mmap, offset):
            self._mmap = mmap
            self._offset = offset
            self._data = mmap[offset * self.SIZEOF:(offset + 1) * self.SIZEOF]
            self.numbers = struct.unpack(self.PACK, self._data)
    
        def save(self):
            self._mmap[self._offset * self.SIZEOF:(self._offset + 1) * self.SIZEOF] = struct.pack(self.PACK, *self.numbers)
    
    
    fd = open("/tmp/three_numbers.dat", "rb+")
    
    obj = ThreeNumbers(fd, 0)
    print obj.numbers
    obj.numbers = (1, 2, 3)
    obj.save()
    
    obj = ThreeNumbers(fd, 0)
    print obj.numbers
    obj.numbers = (0, 0, 0)
    obj.save()
    
    mmap = mmap.mmap(fd.fileno(), 0)
    
    obj = ThreeNumbersMMAP(mmap, 0)
    print obj.numbers
    obj.numbers = (1, 2, 3)
    obj.save()
    
    obj = ThreeNumbersMMAP(mmap, 0)
    print obj.numbers
    obj.numbers = (0, 0, 0)
    obj.save()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-05
      • 2019-07-14
      • 1970-01-01
      • 2015-01-10
      相关资源
      最近更新 更多