gpt4 book ai didi

python - 纯 Python3 中类似 mmap 的行为

转载 作者:行者123 更新时间:2023-12-01 04:05:29 26 4
gpt4 key购买 nike

我想以最低的开发成本将 re 模块与流一起使用,但不一定是文件流。

对于文件流,有 mmap 模块能够模拟字符串,因此可以与 re 一起自由使用。

现在我想知道 mmap 如何设法制作一个 re 可以进一步重用的对象。如果我只是传递任何内容,re 会保护自己免受使用与 TypeError: Expected string or bytes-like object 过于不兼容的对象的影响。所以我想我应该创建一个派生自 stringbytes 的类,并重写一些方法,例如 __getitem__ 等(这直观地适合Python 的鸭子类型哲学),并使它们与我的原始流交互。但是,这似乎根本不起作用 - 我的覆盖完全被忽略。

是否可以在纯 Python 中创建这样一个“惰性”字符串,无需 C 扩展?如果是这样,怎么办?

一些忽略替代解决方案的背景:

  • 无法使用mmap(流内容不是文件)
  • 无法将整个内容转储到 HDD(太慢)
  • 无法将整个内容加载到内存(太大)
  • 可以在运行时查找、了解大小并计算内容

演示字节对修改的抵抗力的示例代码:

class FancyWrapper(bytes):
def __init__(self, base_str):
pass #super() isn't called and yet the code below finds abc, aaa and bbb

print(re.findall(b'[abc]{3}', FancyWrapper(b'abc aaa bbb def')))

最佳答案

嗯,我发现这是不可能的,目前不可能。

  1. Python 的 re模块在内部对字符串进行操作,因为它扫描普通的 C 缓冲区,这要求它接收的对象满足以下属性:

    • 它们的表示必须驻留在系统内存中,
    • 它们的表示必须是线性的,例如它不能包含任何类型的间隙,
    • 它们的表示必须包含我们正在搜索的整体内容。

    所以即使我们设法制作 re使用 bytes 之外的其他内容或string ,我们必须使用mmap类似的行为,即将我们的内容提供者模拟为系统内存中的线性区域。

  2. 但是mmap机制仅适用于文件,事实上,即使这样也非常有限。例如,不能 mmap如果尝试写入一个大文件,如 this answer .

  3. 甚至是 regex模块,其中包含许多 super 重复的添加,例如 (?r) ,不适应 string 之外的内容源和bytes .
<小时/>

为了完整起见:这是否意味着我们完蛋了,无法使用 re 扫描大型动态内容?不必要。如果我们允许限制最大匹配大小,就有办法做到这一点。该解决方案的灵感来自cfi的注释,并将其扩展为二进制文件。

  1. n = 最大匹配大小。
  2. 从位置x开始搜索
  3. 虽然有内容:
    1. 导航至位置x
    2. 读取2*n个字节到扫描缓冲区
    3. 在扫描缓冲区中查找第一个匹配项
    4. 如果找到匹配项:
      1. x = x + match_pos + match_size
      2. 通知 match_posmatch_size
    5. 如果未找到匹配项:
      1. x = x + n

通过使用最大匹配大小两倍的缓冲区可以实现什么效果?想象一下用户搜索 A{3}最大匹配大小设置为 3。如果我们只将 最大匹配大小 字节读取到扫描缓冲区,并且当前 x 的数据包含 AABBBA :

  1. 此迭代将查看 AAB 。没有匹配。
  2. 下一次迭代会将指针移动到x+3
  3. 现在扫描缓冲区将如下所示:BBA 。仍然没有匹配。

这显然很糟糕,简单的解决方案是读取两倍于我们跳过的字节数,以确保扫描缓冲区尾部附近的异常得到解决。

请注意,扫描缓冲区内第一个匹配的短路应该是为了防止其他异常情况,例如缓冲区欠扫描。也许可以对其进行调整,以最大程度地减少对包含多个匹配项的扫描缓冲区的读取,但我想避免事情进一步复杂化。

这可能不是性能最高的算法,但对于我的用例来说已经足够好了,所以我将其留在这里。

关于python - 纯 Python3 中类似 mmap 的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35681835/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com