如何在python 3中有效地将原始字节写入numpy数组数据

疯狂的

在将一些旧的python 2代码迁移到python 3时,我遇到了一些问题,即从字节对象填充结构化的numpy数组。

我有一个解析器,为我可能遇到的每种数据结构类型定义了一个特定的dtype。通常,由于给定的数据结构可能具有可变长度或可变类型的字段,因此这些字段已在numpy数组中表示为对象dtype(np.object #alternatively np.dtype('O'))的字段

该数组是bytearray通过首先填充fixed-dtype字段从字节(或a 获得的此后,可以使用前面的固定字段中的信息来构建任何子数组(包含在“对象”字段中)的dtype。

这是在python 2中工作的此过程的一部分示例(仅处理fixed-dtype字段)。请注意,我们有一个名为的字段'nSamples',大概可以告诉我们该数组的'samples'字段所指向的数组的长度,这将被解释为具有shape(2,)和dtype的numpy数组sampleDtype

fancyDtype = np.dtype([('blah',     '<u4'),
                       ('bleh',      'S5'),
                       ('nSamples', '<u8'),
                       ('samples',    'O')])

sampleDtype = np.dtype([('sampleId', '<u2'),
                        ('val',      '<f4')])

bytesFromFile = bytearray(
    b'*\x00\x00\x00hello\x02\x00\x00\x00\x00\x00\x00\x00\xd0\xb5'
    b'\x14_\xa1\x7f\x00\x00"\x00\x00\x00\x80?]\x00\x00\x00\xa0@')

arr = np.zeros((1,), dtype=fancyDtype)
numBytesFixedPortion = 17

# Start out by just reading the fixed-type portion of the array
arr.data[:numBytesFixedPortion] = bytesFromFile[:numBytesFixedPortion]
memoryview(arr.data)[:numBytesFixedPortion] = bytesFromFile[:numBytesFixedPortion]

最后两个语句都可以在python 2.7中使用。

值得注意的是,如果我输入

arr.data

我得到了<read-write buffer for 0x7f7a93bb7080, size 25, offset 0 at 0x7f7a9339cf70>,这告诉我这是一个缓冲区。显然,memoryview(arr.data)返回一个memoryview对象。

这两个语句在python 3.6中引发以下异常:

NotImplementedError: memoryview: unsupported format T{I:blah:5s:bleh:=Q:nSamples:O:samples:}

这告诉我numpy返回的data属性访问类型是amemoryview而不是a buffer它还告诉我,它memoryviews在python 2.7中有效,但在python 3.6中却不行。

我在numpy的问题跟踪器中发现了一个类似的问题:https : //github.com/numpy/numpy/issues/13617但是,该问题很快被关闭,numpy开发人员指出这是的错误ctypes由于ctypes是内置的,我有点希望仅对其进行更新以得到修复。

我最终确实偶然发现了一个可行的解决方案,尽管它花费的时间大约是python 2.7方法的两倍。它是:

import struct
struct.pack_into(
    'B' * numBytesFixedPortion,  # fmt
    arr.data,                    # buffer
    0,                           # offset
    *buf[:numBytesFixedPortion]  # unpacked byte values
)

一位同事还建议尝试使用此解决方案:

arrView = arr.view('u1')
arrView[:numBytesFixedPortion] = buf[:numBytesFixedPortion]

但是,在执行此操作时,出现异常:

File "/home/tintedFrantic/anaconda2/envs/py3/lib/python3.6/site-packages/numpy/core/_internal.py", line 461, in _view_is_safe
    raise TypeError("Cannot change data-type for object array.")
TypeError: Cannot change data-type for object array.

请注意,我在python 2.7和3.6中都遇到了此异常。似乎numpy不允许在具有任何object字段的阵列上进行查看(此外:通过注释掉numpy代码中对对象类型字段的检查,我能够使numpy正确地做到这一点,尽管这似乎是一个危险的解决方案(也不是一种非常可移植的解决方案))。

我也尝试过创建单独的数组,一个数组带有fixed-dtype字段,另一个数组带有object-dtype字段,然后numpy.lib.recfunctions.merge_arrays用于合并它们。失败的原因是我不记得一条神秘的消息。

我有点茫然。我只想向numpy数组的基础内存写入一些任意字节,然后高效地进行操作。这似乎并不难,但我还没有找到一种好的方法。我想要一个也不是hack的解决方案,因为这将进入需要高可靠性的系统。如果没有更好的struct.pack_into()办法,我将使用该解决方案,但我希望那里的人知道更好的办法。顺便说一句,不使用object-dtype字段不是可行的选择,因为这样做的成本太高了。

如果重要的话,我正在python 2.7中使用numpy 1.16.2,对于python 3.6使用1.17.4。

疯狂的

根据@nawsleahcimnoraa的建议,我发现在python 3.3+中(而不是在python 2.7中),在我的python 3环境中memoryview返回对象arr.data有一个cast()方法。因此,我可以

arr.data.cast('B')[startIdx:endIdx] = buf[:numBytes]

这更像我在python 2.7中的样子。它比struct上面方法简洁得多,并且性能也更好

我在测试这些解决方案时注意到的一件事是,通常,python 3解决方案比python 2版本慢。例如,我struct同时使用python 2和python 3尝试了该解决方案,发现python 3的处理时间显着增加。

我还发现相同版本的不同python环境之间存在相当大的差异。例如,我发现python 3.6的系统安装比python 3.6的虚拟环境安装表现更好,因此看来结果可能很大程度上取决于给定环境的配置。

总的来说,我对使用cast()返回的memoryview对象方法的结果感到满意,arr.data并将暂时使用它。但是,如果有人发现更好的方法,我仍然很想听听。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在Python中有效地将参数解译到数据库

如何在python中有效地将字典中的值分组

Spark:如何有效地将数据帧写入S3

如何有效地将numpy数组中的对应元素相乘?

如何有效地将随机垂直段添加到 numpy 数组中?

如何在C ++ 11中有效地返回大数据

如何在Python中有效地匹配两个数组值?

如何有效地从 3d numpy 数组中删除行和列?

如何在Java中有效地将二进制字符串转换为二进制字节数组?

如何在 Python 中有效地搜索和访问数据帧中的某些单元格?

如何有效地将数组解码为pandas数据框中的列

如何在Python中有效地计算多个文档中的双字母组

如何有效地将 X,Y,RGB_COLOR_INT 熊猫数据帧中的数据放入类似图像的画布 numpy 数组中?

如何有效地将字节数组转换为字符串

在python中有效地连接许多大型3维数组

如何在Haskell中有效地写入大文件

如何有效地将2维数组中的每个元素乘以Numpy中的1维数组?

如何有效地将大型2D数组写入CSV文件

如何在C ++中有效地将数字值重新分配给字符数组

如何从宽格式的数据中有效地在 R 中绘制大量图形?

如何使用 ruby 有效地将数据二进制写入 gcs?

如何习惯/有效地将数据从“读取+搜索”传输到“写入”?

使用Python数据框将数百万行有效地写入文件

在Python3中有效地切片字符串

如何有效地操作大型numpy数组

如何有效地组合许多numpy数组?

如何在numpy中有效地计算高斯核矩阵?

如何在numpy中有效地实现x [i] [j] = y [i + j]?

如何有效地将X模Y添加到numpy数组中的每个元素?