geekdoc-python-zh/docs/askpython/mmap-function.md

8.2 KiB
Raw Permalink Blame History

Python 中的 mmap 函数——快速参考

原文:https://www.askpython.com/python-modules/mmap-function

Python 中的文件 I/O 有很多方法mmap 是最酷但很少使用的方法。在本教程中,我们将学习 Python 中的 mmap 函数,还将学习内存映射,这是 mmap 函数的基本概念。

什么是内存映射?

内存映射是一个过程,通过该过程,机器级结构被用来从磁盘直接映射文件以供程序使用。它将磁盘中的整个文件映射到计算机程序地址空间中的一系列地址。该程序可以像访问随机存储器中的数据一样访问磁盘上的文件。

计算机中的内存管理

为了清楚地理解内存映射和 mmap 工作背后的过程,让我们简单地了解一下计算机内存的类型。

  • 物理内存:是随机存取存储器(RAM),属于易失性内存。当程序处于活动状态时,它可供程序使用。
  • 虚拟内存:如果我们有一台 64 位的机器,我们可以访问多达 170 亿千兆字节的数据。但实际上,我们的个人电脑的物理内存最大为 8 或 16 千兆字节。如果我们运行较大的程序,计算机将物理内存映射到其虚拟空间,并使用称为交换空间的部分存储磁盘来补偿较少的内存,即使文件太大,我们也不必担心文件的大小。在使用期间,不同的分页技术用于将数据从磁盘交换到内存。
  • 共享内存:在分页和虚拟内存等技术的帮助下,多个程序可以使用单个物理内存同时运行,即使它的容量很低。没有被使用的数据被送到交换内存,要被使用的数据被复制到主内存,这样所有的程序都工作了。

mmap 函数使用虚拟内存的概念,让程序看起来好像有一个大文件被加载到了主存中。

但实际上,文件只存在于磁盘上。操作系统只是将文件的地址映射到程序的地址空间,这样程序就可以访问该文件。

Python 中如何使用 mmap 函数?

我们可以使用 mmap 模块进行文件 I/O而不是简单的文件操作。让我们借助下面的例子来理解如何使用 mmap。

#import module
import mmap

#define filepath
filepath="/home/aditya1117/askpython/sample.txt"

#create file object using open function call
file_object= open(filepath,mode="r",encoding="utf8")

#create an mmap object using mmap function call
mmap_object= mmap.mmap(file_object.fileno(),length=0,access=mmap.ACCESS_READ,offset=0)

#read data from mmap object
txt=mmap_object.read()

#print the data
print("Data read from file in byte format is:")
print(txt)
print("Text data is:")
print(txt.decode())

输出:

Data read from file in byte format is:
b'This is a sample file for mmap tutorial.\n'
Text data is:
This is a sample file for mmap tutorial.

在上面的例子中,

  1. 我们首先导入mmap 模块
  2. 然后定义文件在磁盘中的文件路径
  3. 然后,我们使用 open()系统调用创建 file_object
  4. 在获得文件对象后,我们使用 mmap 函数创建文件到程序地址空间的内存映射
  5. 然后我们从 mmap 对象中读取数据
  6. 并打印数据。

mmap 功能描述

mmap_object= mmap.mmap(file_object.fileno(),length=0,access=mmap.ACCESS_READ,offset=0)

mmap 需要一个文件描述符作为第一个参数。

参数 length 以字节为单位获取要映射的内存大小,参数 access 通知内核程序将如何访问内存。

参数 offset 指示程序在 offset 中指定的特定字节之后创建文件的内存映射。

  • 第一个参数的文件描述符由 file 对象的 fileno()方法提供。
  • 如果我们希望系统自动选择足够的内存来映射文件,那么可以将第二个参数中的长度指定为 0。
  • access 参数有许多选项。 ACCESS_READ 允许用户程序仅从映射存储器中读取。访问 _ 复制访问 _ 写入提供写入模式访问。在 ACCESS_WRITE 模式下,程序可以更改映射内存和文件,但在 ACCESS_COPY 模式下,仅映射内存被更改。
  • 当我们希望从起始地址映射文件时offset 参数通常被指定为 0。

如何将数据写入内存映射文件?

要将一些数据写入内存映射文件,我们可以使用 ACCESS 参数中的 ACCESS_WRITE 选项,并使用 mmap_object.write() 函数,通过在 r+ 模式下打开文件,在创建文件对象后写入文件。

这里我们必须注意到mmap 不允许映射空文件。这是因为空文件不需要内存映射,因为它只是一个内存缓冲区。

如果 我们将使用“w”模式打开一个文件mmap 将导致 ValueError。

#import module
import mmap

#define filepath
filepath="/home/aditya1117/askpython/sampleoutput.txt"

#create file object using open function call
file_object= open(filepath,mode="r+",encoding="utf8")
print("Initial data in the file is:")
print(file_object.read())

#create an mmap object using mmap function call
mmap_object= mmap.mmap(file_object.fileno(),length=0,access=mmap.ACCESS_WRITE,offset=0 )

#write something into file
text="Aditya is writing this text to file  "
mmap_object.write(bytes(text,encoding="utf8"))

# read data from file 
nfile_object= open(filepath,mode="r+",encoding="utf8")

print("Modified data from file is:")
print(nfile_object.read())

输出:

Initial data in the file is:
This is a sample file for mmap tutorial in python.

Modified data from file is:
Aditya is writing this text to file  al in python.

关于上面的例子,我们必须记住的重要一点是,在写入 mmap 之前,输入应该被转换成字节

此外mmap 从文件的第一个地址开始写入数据,并覆盖初始数据。如果我们必须保存以前的数据,我们可以通过在 mmap 函数调用中指定适当的偏移量来实现。

如何使用 mmap 访问文件的某一部分?

我们可以使用 mmap 对象直接访问文件的一部分。mmap 对象可以被切片,就像我们在 python 列表上使用切片一样。

mmap 对象显示了字符串的行为,在字符串上进行的许多操作都可以应用到 mmap 对象上。

当我们在 Python 列表上使用切片时mmap 对象可以被切片。假设我们想读取文件的第 10 到 99 个字符。我们可以这样做,如下例所示。

#import module
import mmap

#define filepath
filepath="/home/aditya1117/askpython/sample.txt"

#create file object using open function call
file_object= open(filepath,mode="r",encoding="utf8")

#create an mmap object using mmap function call
mmap_object= mmap.mmap(file_object.fileno(),length=0,access=mmap.ACCESS_READ,offset=0 )
print("Complete data in byte format is:")
print(mmap_object.read())
print("Data from 9th to 97th character is:")
#print 10th to 99th character
print(mmap_object[9:98])

输出:

Complete data in byte format is:
b'We can access a part of file directly using mmap objects. mmap objects can be sliced as we use slicing on python lists.mmap objects show the behavior of strings and many operations which are done on strings can be applied to mmap objects.mmap objects can be sliced as we use lists in python. Suppose we want to read from the 10th to 99th character of the file. We can do so as shown in the following example.\n'
Data from 9th to 97th character is:
b'cess a part of file directly using mmap objects. mmap objects can be sliced as we use sli'

Python 中为什么要用 mmap

简单的读/写操作在执行过程中会产生许多系统调用,这会导致在该过程中在不同的缓冲区中多次复制数据。

使用 mmap 在性能方面为我们提供了显著的改进,因为它跳过了那些函数调用和缓冲操作,特别是在需要大量文件 I/O 的程序中。

结论

在本教程中,首先,我们已经看到了什么是内存映射。然后我们看了内存管理技术。然后我们通过各种例子看到了如何在 Python 中使用 mmap也看到了函数工作背后的一些技术方面。快乐学习