首页 > 解决方案 > Python mmap.mmap() 到类似字节的对象?

问题描述

的文档mmap说“内存映射文件对象的行为既bytearray像文件对象又像文件对象”。

但是,这似乎并没有扩展到标准for循环:至少对于我目前使用的 Linux 上的 Python 3.8.5,每个mmap.mmap()迭代器元素都是一个单字节bytes,而对于 abytearray和普通文件访问每个元素是一个int更新。更正:对于正常的文件访问,它是可变大小的bytes;见下文。

这是为什么?更重要的是,我怎样才能有效地从 an 中获取一个类似字节的对象mmap,所以一个不仅索引而且for还给我一个的对象int?(通过有效,我的意思是我想避免额外的复制、强制转换等)


这是演示该行为的代码:

#!/usr/bin/env python3.8

def print_types(desc, x):
    for el in setmm: break   ### UPDATE: bug here, `setmm` should be `x`, see comments
    # `el` is now the first element of `x`
    print('%-30s: type is %-30s, first element is %s' % (desc,type(x),type(el)))
    try: print('%72s(first element size is %d)' % (' ', len(el)))
    except: pass # ignore failure if `el` doesn't support `len()`

setmm = bytearray(b'hoi!')
print_types('bytearray', setmm)

with open('set.mm', 'rb') as f:
    print_types('file object', f)

with open('set.mm', 'rb') as f:
    setmm = f.read()
    print_types('file open().read() result', setmm)

import mmap
with open('set.mm', 'rb') as f:
    setmm = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)
    print_types('file mmap.mmap() result', setmm)

这导致

bytearray                     : type is <class 'bytearray'>           , first element type is <class 'int'>
file object                   : type is <class '_io.BufferedReader'>  , first element type is <class 'int'>
file open().read() result     : type is <class 'bytes'>               , first element type is <class 'int'>
file mmap.mmap() result       : type is <class 'mmap.mmap'>           , first element type is <class 'bytes'>
                                                                        (first element size is 1)

更新。修复了furas在评论中指出的错误,结果变为

bytearray                     : type is <class 'bytearray'>           , first element is <class 'int'>
file object                   : type is <class '_io.BufferedReader'>  , first element is <class 'bytes'>
                                                                        (first element size is 38)
file open().read() result     : type is <class 'bytes'>               , first element is <class 'int'>
file mmap.mmap() result       : type is <class 'mmap.mmap'>           , first element is <class 'bytes'>
                                                                        (first element size is 1)

这回答了会发生什么:由于某种原因,迭代 anmmap就像迭代文件一样,bytes每次都返回 a ,但不是像文件那样使用完整的行,而是单字节块。

我的主要问题仍然没有改变:我怎样才能有效地使mmap行为像字节对象一样(即 indexing 和forgive int)?

标签: pythonpython-3.xiteratormmap

解决方案


我怎样才能有效地让 mmap 表现得像一个字节对象(即,索引和 for give int)?

bytes是一个在内存中包含数据的对象。但重点mmap是不要将所有数据加载到内存中。

如果要获取一个bytes包含文件全部内容的对象,则该文件和整个内容open()一样正常。read()使用mmap()它对自己不利。

也许您想使用memoryview,它可以由bytes或构建,mmap()并且会给您一个统一的 API。


推荐阅读