Python 3.73 插入到 bytearray =“对象不能重新调整大小”

Posted

技术标签:

【中文标题】Python 3.73 插入到 bytearray =“对象不能重新调整大小”【英文标题】:Python 3.73 inserting into bytearray = "object cannot be re-sized" 【发布时间】:2020-09-29 05:53:35 【问题描述】:

我正在处理来自文件数据的字节数组。我是opening 它是'r+b',所以可以更改为二进制。

在Python 3.7 docs 中,它解释了RegEx 的finditer() 可以使用m.start()m.end() 来标识匹配的开始和结束。

在问题Insert bytearray into bytearray Python 中,答案说可以通过使用切片对字节数组进行插入。但是尝试这样做时,会出现以下错误:BufferError: Existing exports of data: object cannot be re-sized

这是一个例子:

    pat = re.compile(rb'0.?\d* [nN]')   # regex, binary "0[.*] n"
    with open(file, mode='r+b') as f:   # updateable, binary
        d = bytearray(f.read())         # read file data as d [as bytes]
        it = pat.finditer(d)            # find pattern in data as iterable
        for match in it:                # for each match,
            m = match.group()           # bytes of the match string to binary m
            ...
            val = b'0123456789 n'
            ...
            d[match.start():match.end()] = bytearray(val)

在文件中,匹配是0 n,我试图用0123456789 n 替换它,所以将插入9 个字节。 可以用这段代码成功地改变文件,只是没有增加的大小。我究竟做错了什么?这是显示所有非增加文件大小操作的输出,但在插入数字时失败:

*** Changing b'0.0032 n' to b'0.0640 n'
len(d): 10435, match.start(): 607, match.end(): 615, len(bytearray(val)): 8
*** Found: "0.0126 n"; set to [0.252] or custom:
*** Changing b'0.0126 n' to b'0.2520 n'
len(d): 10435, match.start(): 758, match.end(): 766, len(bytearray(val)): 8
*** Found: "0 n"; set to [0.1] or custom:
*** Changing b'0 n' to b'0.1 n'
len(d): 10435, match.start(): 806, match.end(): 809, len(bytearray(val)): 5
Traceback (most recent call last):
  File "fixV1.py", line 190, in <module>
    main(sys.argv)
  File "fixV1.py", line 136, in main
    nchanges += search(midfile)     # perform search, returning count
  File "fixV1.py", line 71, in search
    d[match.start():match.end()] = bytearray(val)
BufferError: Existing exports of data: object cannot be re-sized

【问题讨论】:

len(d)match.start()match.end()len(bytearray(val)) 的值是多少? 这部分正则表达式 0.?\d* 对您意味着什么? RegEx 0.?\d* [nN] 表示“数据以 0 开头,有一个可选的 . 和 0 个或多个数字。然后是一个“”字符,以及一个 nN。”它似乎在所有情况下都正确匹配。 【参考方案1】:

这是一个简单的例子,很像在迭代期间修改一个可迭代对象:

it = pat.finditer(d) creates a buffer 来自 bytearray 对象。这反过来又“锁定”了字节数组对象的大小。 d[match.start():match.end()] = bytearray(val) 尝试修改“锁定”字节数组对象的大小。

就像在迭代列表时尝试更改列表大小会失败一样,在迭代缓冲区时尝试更改字节数组大小也会失败。

您可以将该对象的副本提供给finditer()

有关缓冲区以及 Python 如何在后台工作的更多信息,请参阅Python docs。


另外,请记住,您实际上并没有修改文件。您需要将数据写回文件,或使用memory mapped files。如果您正在寻找效率,我建议后者。

【讨论】:

这个想法是(起初)打开文件,读取它(进入 [d]),通过添加字节对其进行修改,然后将其写回。但这在切片插入时失败,而不是在文件保存时失败。在 MMAP 的文档中,它显示“# note that new content must have the same size”。我想问题变成了,可以将 [d] 创建为非锁定吗? @rdtsc 长度可以更改。是的,它在 slice-insert 上失败了,因为它被锁定了。做到这一点的唯一方法是立即或懒惰地创建数据副本。尝试执行it = pat.finditer(d.copy()),您会发现它会起作用。

以上是关于Python 3.73 插入到 bytearray =“对象不能重新调整大小”的主要内容,如果未能解决你的问题,请参考以下文章

Python学习笔记015——序列(字节数组 bytearray)

Python函数-bytearray()

请教Python3 bytearray 的问题

Python内置函数—bytearray

python 内置函数bytearray

Python内置函数——bytearray()-暂疑