mmap --- پشتیبانی از پروندههای نگاشتشده به حافظه (memory-mapped file)¶
دسترسپذیری: not WASI.
این ماژول روی WebAssembly کار نمیکند یا در دسترس نیست. برای اطلاعات بیشتر، سکوهای WebAssembly را ببینید.
اشیای پرونده نگاشتشده به حافظه، هم مانند bytearray و هم مانند اشیای پرونده رفتار میکنند. شما میتوانید از اشیای mmap در بیشتر مواردی استفاده کنید که انتظار میرود یک bytearray وجود داشته باشد؛ برای مثال، میتوانید از ماژول re برای جستجو در یک پرونده نگاشتشده به حافظه استفاده کنید. همچنین میتوانید یک بایت را با obj[index] = 97 تغییر دهید، یا یک زیردنباله را با انتساب به یک اسلایس تغییر دهید: obj[i1:i2] = b'...'. همچنین میتوانید دادهها را از موقعیت فعلی پرونده بخوانید و بنویسید، و با seek() در پرونده به موقعیتهای مختلف حرکت کنید.
یک پرونده نگاشتشده به حافظه (memory-mapped file) توسط سازندهی mmap ایجاد میشود، که در یونیکس و ویندوز متفاوت است. در هر دو حالت، باید توصیفگر پروندهای را که برای بهروزرسانی باز شده است، فراهم کنید. اگر میخواهید یک شیء پرونده پایتون موجود را نگاشت کنید، از متد fileno() آن برای به دست آوردن مقدار صحیح پارامتر fileno استفاده کنید. در غیر این صورت، میتوانید پرونده را با استفاده از تابع os.open() باز کنید، که توصیفگر پرونده را مستقیماً برمیگرداند (پرونده همچنان باید پس از اتمام کار بسته شود).
توجه
اگر میخواهید برای یک پرونده قابلنوشتن و بافرشده، یک نگاشت حافظه (memory-mapping) ایجاد کنید، باید ابتدا پرونده را flush() کنید. این کار برای اطمینان از اینکه تغییرات محلی در بافرها واقعاً در دسترس نگاشت باشند، ضروری است.
برای هر دو نسخهی Unix و Windows از سازنده، میتوانید access را بهعنوان یک پارامتر کلیدواژهای اختیاری مشخص کنید. access یکی از چهار مقدار را میپذیرد: ACCESS_READ، ACCESS_WRITE، یا ACCESS_COPY برای مشخص کردن حافظهی فقطخواندنی، حافظهی نوشتنهمزمان (write-through) یا حافظهی کپی هنگام نوشتن (copy-on-write) بهترتیب، یا ACCESS_DEFAULT برای واگذاری به prot. access در هر دو Unix و Windows قابل استفاده است. اگر access مشخص نشده باشد، mmap در Windows یک نگاشت نوشتنهمزمان (write-through) برمیگرداند. مقدارهای اولیهی حافظه برای هر سه نوع دسترسی از پرونده مشخصشده گرفته میشوند. انتساب به یک نگاشت حافظهی ACCESS_READ باعث پرتاب استثنای TypeError میشود. انتساب به یک نگاشت حافظهی ACCESS_WRITE هم بر حافظه و هم بر پرونده زیرین تأثیر میگذارد. انتساب به یک نگاشت حافظهی ACCESS_COPY بر حافظه تأثیر میگذارد، اما پرونده زیرین را بهروزرسانی نمیکند.
تغییر یافته در نسخهی 3.7: ثابت ACCESS_DEFAULT اضافه شد.
برای نگاشت حافظهی ناشناس، باید -1 بهعنوان fileno به همراه طول ارسال شود.
- class mmap.mmap(fileno, length, tagname=None, access=ACCESS_DEFAULT, offset=0)¶
(نسخهی ویندوز) length بایت از پروندهای که با دسته پرونده fileno مشخص شده است را نگاشت میکند و یک شیء mmap ایجاد میکند. اگر length بزرگتر از اندازهی فعلی پرونده باشد، پرونده گسترش داده میشود تا شامل length بایت شود. اگر length برابر
0باشد، حداکثر طول نگاشت برابر اندازهی فعلی پرونده است، مگر اینکه پرونده خالی باشد؛ در این صورت ویندوز یک استثنا پرتاب میکند (شما نمیتوانید یک نگاشت خالی در ویندوز ایجاد کنید).tagname، اگر مشخص شده باشد و
Noneنباشد، رشتهای است که نام برچسب را برای نگاشت مشخص میکند. ویندوز به شما امکان میدهد نگاشتهای متفاوت بسیاری برای یک پرونده یکسان داشته باشید. اگر نام یک برچسب موجود را مشخص کنید، آن برچسب باز میشود، در غیر این صورت برچسب جدیدی با این نام ایجاد میشود. اگر این پارامتر حذف شود یاNoneباشد، نگاشت بدون نام ایجاد میشود. اجتناب از استفاده از پارامتر tagname به قابلحمل نگهداشتن کد شما بین یونیکس و ویندوز کمک میکند.offset میتواند بهعنوان یک آفست از نوع عدد صحیح غیرمنفی مشخص شود. ارجاعهای mmap نسبت به آفست از ابتدای پرونده خواهند بود. offset بهطور پیشفرض ۰ است. offset باید مضربی از
ALLOCATIONGRANULARITYباشد.یک رویداد حسابرسی
mmap.__new__را با آرگومانهایfileno،length،access،offsetپرتاب میکند.
- class mmap.mmap(fileno, length, flags=MAP_SHARED, prot=PROT_WRITE | PROT_READ, access=ACCESS_DEFAULT, offset=0, *, trackfd=True)
(نسخهی یونیکس) length بایت از پرونده مشخصشده با توصیفگر پرونده fileno را نگاشت میکند و یک شیء mmap برمیگرداند. اگر length برابر
0باشد، حداکثر طول نگاشت برابر اندازهی فعلی پرونده در هنگام فراخوانیmmapخواهد بود.flags ماهیت نگاشت را مشخص میکند.
MAP_PRIVATEیک نگاشت خصوصی با کپی-در-نوشتن (copy-on-write) ایجاد میکند، بنابراین تغییرات در محتوای شیء mmap برای این فرایند خصوصی خواهد بود وMAP_SHAREDنگاشتی ایجاد میکند که با تمام فرایندهای دیگری که ناحیههای یکسانی از پرونده را نگاشت میکنند، به اشتراک گذاشته میشود. مقدار پیشفرضMAP_SHAREDاست. برخی سیستمها پرچمهای ممکن بیشتری دارند که فهرست کامل آنها در MAP_* constants مشخص شده است.prot، در صورت مشخص شدن، محافظت دلخواه از حافظه را تعیین میکند؛ دو مقدار از مفیدترین مقادیر عبارتند از
PROT_READوPROT_WRITE، برای مشخص کردن اینکه صفحهها میتوانند خوانده یا نوشته شوند. prot بهطور پیشفرضPROT_READ | PROT_WRITEاست.میتوان access را بهجای flags و prot بهعنوان یک پارامتر کلیدواژهای اختیاری مشخص کرد. مشخص کردن همزمان flags، prot و access خطا است. برای آگاهی از چگونگی استفاده از این پارامتر، توضیح access در بالا را ببینید.
میتوان offset را بهصورت یک آفست عدد صحیح غیرمنفی مشخص کرد. ارجاعهای mmap نسبت به آفست از ابتدای پرونده خواهند بود. مقدار پیشفرض offset برابر ۰ است. offset باید مضربی از
ALLOCATIONGRANULARITYباشد که در سیستمهای یونیکس برابرPAGESIZEاست.اگر trackfd برابر
Falseباشد، توصیفگر پرونده مشخصشده توسط fileno تکثیر نخواهد شد و شیءmmapحاصل با پرونده زیربنایی نگاشت مرتبط نخواهد بود. این بدان معناست که متدهایsize()وresize()ناموفق خواهند بود. این حالت برای محدود کردن تعداد توصیفگرهای پرونده باز مفید است.برای اطمینان از اعتبار نگاشت حافظهی ایجادشده، پرونده مشخصشده با توصیفگر fileno، بهصورت داخلی و بهطور خودکار با ذخیرهگاه پشتیبان فیزیکی در macOS همگامسازی میشود.
تغییر یافته در نسخهی 3.13: پارامتر trackfd افزوده شد.
این مثال روش سادهای برای استفاده از
mmapنشان میدهد:import mmap # write a simple example file with open("hello.txt", "wb") as f: f.write(b"Hello Python!\n") with open("hello.txt", "r+b") as f: # memory-map the file, size 0 means whole file mm = mmap.mmap(f.fileno(), 0) # read content via standard file methods print(mm.readline()) # prints b"Hello Python!\n" # read content via slice notation print(mm[:5]) # prints b"Hello" # update content using slice notation; # note that new content must have same size mm[6:] = b" world!\n" # ... and read again using standard file methods mm.seek(0) print(mm.readline()) # prints b"Hello world!\n" # close the map mm.close()
همچنین میتوان از
mmapبهعنوان یک مدیر زمینه در دستورwithاستفاده کرد:import mmap with mmap.mmap(-1, 13) as mm: mm.write(b"Hello world!")
اضافه شده در نسخهی 3.2: پشتیبانی از مدیر زمینه.
مثال بعدی نحوه ایجاد یک نگاشت ناشناس (anonymous map) و مبادله دادهها بین فرایندهای والد و فرزند را نشان میدهد:
import mmap import os mm = mmap.mmap(-1, 13) mm.write(b"Hello world!") pid = os.fork() if pid == 0: # In a child process mm.seek(0) print(mm.readline()) mm.close()
یک رویداد حسابرسی
mmap.__new__را با آرگومانهایfileno،length،access،offsetپرتاب میکند.اشیای پرونده نگاشتشده به حافظه از متدهای زیر پشتیبانی میکنند:
- close()¶
mmap را میبندد. فراخوانیهای بعدی به سایر متدهای شیء، منجر به پرتاب استثنای ValueError خواهند شد. این کار پرونده باز را نمیبندد.
- closed¶
Trueاگر پرونده بسته باشد.اضافه شده در نسخهی 3.2.
- find(sub[, start[, end]])¶
کمترین اندیسی در شیء را برمیگرداند که زیردنبالهی sub در آن پیدا میشود، بهگونهای که sub در بازهی [start، end] قرار داشته باشد. آرگومانهای اختیاری start و end همانند نمادگذاری اسلایس تفسیر میشوند. در صورت شکست،
-1را برمیگرداند.تغییر یافته در نسخهی 3.5: اکنون bytes-like object قابل نوشتن پذیرفته میشود.
- flush()¶
- flush(offset, size, /)
تغییرات اعمالشده بر نسخهی درونحافظهای یک پرونده را به دیسک مینویسد. بدون استفاده از این فراخوانی، هیچ تضمینی وجود ندارد که تغییرات پیش از از بین رفتن شیء به دیسک نوشته شوند. اگر offset و size مشخص شده باشند، فقط تغییرات در محدودهی مشخصشده از بایتها به دیسک نوشته میشوند؛ در غیر این صورت، کل محدودهی نگاشت به دیسک نوشته میشود. offset باید مضربی از
PAGESIZEیاALLOCATIONGRANULARITYباشد.Noneبرای نشان دادن موفقیت برگردانده میشود. در صورت شکست فراخوانی، یک استثنا پرتاب میشود.تغییر یافته در نسخهی 3.8: پیشتر، در صورت موفقیت یک مقدار غیرصفر بازگردانده میشد؛ در ویندوز، در صورت خطا صفر بازگردانده میشد. در یونیکس، در صورت موفقیت یک مقدار صفر بازگردانده میشد؛ در صورت خطا یک استثنا پرتاب میشد.
- madvise(option[, start[, length]])¶
توصیهی option را دربارهی ناحیهی حافظهای که از start شروع میشود و به طول length بایت ادامه دارد، به هسته ارسال کنید. option باید یکی از ثابتهای MADV_* موجود در سیستم باشد. اگر start و length حذف شوند، کل نگاشت پوشش داده میشود. در برخی سیستمها (از جمله لینوکس)، start باید مضربی از
PAGESIZEباشد.دسترسپذیری: سیستمهای دارای فراخوان سیستمی
madvise().اضافه شده در نسخهی 3.8.
- move(dest, src, count)¶
count بایت را که از آفست src شروع میشوند، به اندیس مقصد dest کپی میکند. اگر mmap با
ACCESS_READایجاد شده باشد، فراخوانیهای move یک استثنایTypeErrorپرتاب خواهند کرد.
- read([n])¶
یک
bytesحاوی حداکثر n بایت را برمیگرداند که از موقعیت فعلی پرونده شروع میشود. اگر آرگومان حذف شده باشد،Noneباشد یا منفی باشد، همه بایتها را از موقعیت فعلی پرونده تا انتهای نگاشت برمیگرداند. موقعیت پرونده بهروزرسانی میشود تا به بعد از بایتهای برگرداندهشده اشاره کند.تغییر یافته در نسخهی 3.3: آرگومان میتواند حذف شود یا
Noneباشد.
- read_byte()¶
یک بایت در موقعیت فعلی پرونده را بهعنوان یک عدد صحیح برمیگرداند و موقعیت پرونده را ۱ واحد جلو میبرد.
- readline()¶
یک خط واحد را برمیگرداند که از موقعیت فعلی پرونده شروع میشود و تا خط جدید بعدی ادامه دارد. موقعیت پرونده بهروزرسانی میشود تا به بعد از بایتهای برگرداندهشده اشاره کند.
- resize(newsize)¶
اندازهی نگاشت و پرونده زیربنایی را، در صورت وجود، تغییر میدهد.
تغییر اندازهی نگاشتی که با access برابر با
ACCESS_READیاACCESS_COPYایجادشده است، باعث پرتاب یک استثنایTypeErrorمیشود. تغییر اندازهی نگاشتی که با تنظیم trackfd رویFalseایجادشده است، باعث پرتاب یک استثنایValueErrorمیشود.در ویندوز: تغییر اندازهی نگاشت (map) در صورتی که نگاشتهای دیگری بر روی همان پرونده نامدار وجود داشته باشند، باعث پرتاب یک
OSErrorمیشود. تغییر اندازهی یک نگاشت ناشناس (یعنی بر روی پرونده صفحهبندی (pagefile)) بدون هیچ پیامی یک نگاشت جدید با دادههای اصلی کپیشده تا طول اندازهی جدید ایجاد میکند.تغییر یافته در نسخهی 3.11: در صورت تلاش برای تغییر اندازه زمانی که نگاشت دیگری در اختیار گرفته شده است، بهدرستی شکست میخورد. امکان تغییر اندازهی نگاشت ناشناس در ویندوز را فراهم میکند
- rfind(sub[, start[, end]])¶
بالاترین اندیسی در شیء را برمیگرداند که زیردنباله sub در آن یافت میشود، بهطوری که sub در بازه [start، end] قرار داشته باشد. آرگومانهای اختیاری start و end مانند نمادگذاری اسلایس تفسیر میشوند. در صورت شکست،
-1را برمیگرداند.تغییر یافته در نسخهی 3.5: اکنون bytes-like object قابل نوشتن پذیرفته میشود.
- seek(pos[, whence])¶
موقعیت فعلی پرونده را تنظیم میکند. آرگومان whence اختیاری است و پیشفرض آن
os.SEEK_SETیا0(موقعیتدهی مطلق پرونده) است؛ مقادیر دیگرos.SEEK_CURیا1(جابهجایی نسبت به موقعیت فعلی) وos.SEEK_ENDیا2(جابهجایی نسبت به پایان پرونده) هستند.تغییر یافته در نسخهی 3.13: موقعیت مطلق جدید بهجای
Noneبرگردانده میشود.
- seekable()¶
برمیگرداند که آیا پرونده از مکانیابی (seeking) پشتیبانی میکند، و مقدار بازگشتی همیشه
Trueاست.اضافه شده در نسخهی 3.13.
- size()¶
طول پرونده را برمیگرداند، که میتواند بزرگتر از اندازهی ناحیهی نگاشتشده به حافظه باشد.
- tell()¶
موقعیت فعلی اشارهگر پرونده را برمیگرداند.
- write(bytes)¶
بایتهای موجود در bytes را در حافظه، در موقعیت فعلی اشارهگر پرونده مینویسد و تعداد بایتهای نوشتهشده را برمیگرداند (هرگز کمتر از
len(bytes)نیست، زیرا اگر نوشتن ناموفق باشد، استثنایValueErrorپرتاب خواهد شد). موقعیت پرونده بهروزرسانی میشود تا به بعد از بایتهای نوشتهشده اشاره کند. اگر mmap باACCESS_READایجاد شده باشد، نوشتن در آن استثنایTypeErrorرا پرتاب خواهد کرد.تغییر یافته در نسخهی 3.5: اکنون bytes-like object قابل نوشتن پذیرفته میشود.
تغییر یافته در نسخهی 3.6: تعداد بایتهای نوشتهشده اکنون برگردانده میشود.
ثابتهای MADV_*¶
- mmap.MADV_NORMAL¶
- mmap.MADV_RANDOM¶
- mmap.MADV_SEQUENTIAL¶
- mmap.MADV_WILLNEED¶
- mmap.MADV_DONTNEED¶
- mmap.MADV_REMOVE¶
- mmap.MADV_DONTFORK¶
- mmap.MADV_DOFORK¶
- mmap.MADV_HWPOISON¶
- mmap.MADV_MERGEABLE¶
- mmap.MADV_UNMERGEABLE¶
- mmap.MADV_SOFT_OFFLINE¶
- mmap.MADV_HUGEPAGE¶
- mmap.MADV_NOHUGEPAGE¶
- mmap.MADV_DONTDUMP¶
- mmap.MADV_DODUMP¶
- mmap.MADV_FREE¶
- mmap.MADV_NOSYNC¶
- mmap.MADV_AUTOSYNC¶
- mmap.MADV_NOCORE¶
- mmap.MADV_CORE¶
- mmap.MADV_PROTECT¶
- mmap.MADV_FREE_REUSABLE¶
- mmap.MADV_FREE_REUSE¶
این گزینهها را میتوان به
mmap.madvise()ارسال کرد. هر گزینهای در هر سامانهای موجود نخواهد بود.دسترسپذیری: سیستمهای دارای فراخوان سیستمی madvise().
اضافه شده در نسخهی 3.8.
ثابتهای MAP_*¶
- mmap.MAP_SHARED¶
- mmap.MAP_PRIVATE¶
- mmap.MAP_32BIT¶
- mmap.MAP_ALIGNED_SUPER¶
- mmap.MAP_ANON¶
- mmap.MAP_ANONYMOUS¶
- mmap.MAP_CONCEAL¶
- mmap.MAP_DENYWRITE¶
- mmap.MAP_EXECUTABLE¶
- mmap.MAP_HASSEMAPHORE¶
- mmap.MAP_JIT¶
- mmap.MAP_NOCACHE¶
- mmap.MAP_NOEXTEND¶
- mmap.MAP_NORESERVE¶
- mmap.MAP_POPULATE¶
- mmap.MAP_RESILIENT_CODESIGN¶
- mmap.MAP_RESILIENT_MEDIA¶
- mmap.MAP_STACK¶
- mmap.MAP_TPRO¶
- mmap.MAP_TRANSLATED_ALLOW_EXECUTE¶
- mmap.MAP_UNIX03¶
اینها پرچمهای مختلفی هستند که میتوان آنها را به
mmap.mmap()ارسال کرد.MAP_ALIGNED_SUPERفقط در FreeBSD در دسترس است وMAP_CONCEALفقط در OpenBSD در دسترس است. توجه داشته باشید که برخی گزینهها ممکن است در برخی سیستمها وجود نداشته باشند.تغییر یافته در نسخهی 3.10: ثابت
MAP_POPULATEاضافه شد.اضافه شده در نسخهی 3.11: ثابت
MAP_STACKاضافه شد.اضافه شده در نسخهی 3.12: ثابتهای
MAP_ALIGNED_SUPERوMAP_CONCEALافزوده شدند.اضافه شده در نسخهی 3.13: ثابتهای
MAP_32BIT،MAP_HASSEMAPHORE،MAP_JIT،MAP_NOCACHE،MAP_NOEXTEND،MAP_NORESERVE،MAP_RESILIENT_CODESIGN،MAP_RESILIENT_MEDIA،MAP_TPRO،MAP_TRANSLATED_ALLOW_EXECUTEوMAP_UNIX03افزوده شدند.