tempfile --- تولید پروندهها و پوشههای موقت¶
کد منبع: Lib/tempfile.py
این ماژول پروندهها و پوشههای موقت ایجاد میکند. این ماژول روی همهی پلتفرمهای پشتیبانیشده کار میکند. TemporaryFile، NamedTemporaryFile، TemporaryDirectory و SpooledTemporaryFile رابطهای سطح بالایی هستند که پاکسازی خودکار را فراهم میکنند و میتوانند بهعنوان مدیران زمینه استفاده شوند. mkstemp() و mkdtemp() توابع سطح پایینتری هستند که به پاکسازی دستی نیاز دارند.
تمام توابع و سازندههای فراخوانیپذیر توسط کاربر، آرگومانهای اضافی میگیرند که امکان کنترل مستقیم بر مکان و نام پروندهها و پوشههای موقت را فراهم میکنند. نام پروندههای استفادهشده در این ماژول شامل رشتهای از نویسههای تصادفی است که امکان ایجاد امن آن پروندهها در پوشههای موقت مشترک را فراهم میکند. برای حفظ سازگاری با نسخههای قبلی، ترتیب آرگومانها کمی عجیب است؛ توصیه میشود برای وضوح بیشتر از آرگومانهای کلیدواژهای استفاده کنید.
این ماژول آیتمهای فراخوانیپذیر توسط کاربر زیر را تعریف میکند:
- tempfile.TemporaryFile(mode='w+b', buffering=-1, encoding=None, newline=None, suffix=None, prefix=None, dir=None, *, errors=None)¶
یک file-like object برمیگرداند که میتوان از آن بهعنوان یک فضای ذخیرهسازی موقت استفاده کرد. این پرونده بهصورت ایمن و با استفاده از همان قوانین
mkstemp()ایجاد میشود. این پرونده به محض بسته شدن از بین میرود (از جمله بستن ضمنی هنگامی که شیء زبالهروبی میشود). در یونیکس، مدخل پرونده در پوشه یا اصلاً ایجاد نمیشود یا بلافاصله پس از ایجاد پرونده حذف میشود. سایر سکوها از این قابلیت پشتیبانی نمیکنند؛ کد شما نباید به داشتن یا نداشتن نام قابلمشاهده در سامانه فایلبندی برای پرونده موقتی که با استفاده از این تابع ایجاد شده است، اتکا کند.میتوان از شیء حاصل بهعنوان یک مدیر زمینه استفاده کرد (به مثالها مراجعه کنید). پس از تکمیل زمینه یا تخریب شیء پرونده، پرونده موقت از سامانه فایلبندی حذف خواهد شد.
پارامتر mode بهطور پیشفرض مقدار
'w+b'دارد تا پرونده ایجادشده بدون بسته شدن قابل خواندن و نوشتن باشد. از حالت دودویی استفاده میشود تا بدون توجه به دادههای ذخیرهشده، در همهی پلتفرمها رفتار یکسانی داشته باشد. buffering، encoding، errors و newline همانطور تفسیر میشوند که برایopen()تفسیر میشوند.پارامترهای dir، prefix و suffix همان معنا و مقادیر پیشفرض
mkstemp()را دارند.شیء برگرداندهشده در سکوهای POSIX یک شیء پرونده واقعی است. در سکوهای دیگر، یک شیء شبهپرونده است که ویژگی
fileآن، شیء پرونده واقعی زیربنایی است.پرچم
os.O_TMPFILEدر صورتی استفاده میشود که در دسترس باشد و کار کند (مخصوص لینوکس، نیازمند هسته لینوکس 3.11 یا جدیدتر).در سکوهایی که نه Posix هستند و نه Cygwin، TemporaryFile نام مستعاری برای NamedTemporaryFile است.
یک رویداد حسابرسی
tempfile.mkstempرا با آرگومانfullpathپرتاب میکند.تغییر یافته در نسخهی 3.5: اکنون در صورت موجود بودن، از پرچم
os.O_TMPFILEاستفاده میشود.تغییر یافته در نسخهی 3.8: پارامتر errors اضافه شد.
- tempfile.NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None, newline=None, suffix=None, prefix=None, dir=None, delete=True, *, errors=None, delete_on_close=True)¶
این تابع دقیقاً مانند
TemporaryFile()عمل میکند، بهجز تفاوتهای زیر:این تابع پروندهای را برمیگرداند که تضمین میشود دارای نام قابل مشاهدهای در سامانه فایلبندی است.
برای مدیریت پرونده نامدار، این تابع پارامترهای
TemporaryFile()را با پارامترهای delete و delete_on_close گسترش میدهد که تعیین میکنند آیا پرونده نامدار باید بهطور خودکار حذف شود یا خیر، و این حذف چگونه انجام شود.
شیء برگرداندهشده همیشه یک file-like object است که ویژگی
fileآن، شیء پرونده واقعی زیرین است. این شیء شبهپرونده میتواند در یک دستورwith، درست مانند یک پرونده معمولی استفاده شود. نام پرونده موقت را میتوان از ویژگیnameشیء شبهپرونده برگرداندهشده بازیابی کرد. در یونیکس، برخلافTemporaryFile()، مدخل پوشه بلافاصله پس از ایجاد پرونده حذف نمیشود.اگر delete درست باشد (پیشفرض) و delete_on_close درست باشد (پیشفرض)، پرونده به محض بسته شدن حذف میشود. اگر delete درست و delete_on_close نادرست باشد، پرونده فقط هنگام خروج از مدیر زمینه حذف میشود، یا در غیر این صورت وقتی file-like object نهایی میشود. حذف در این حالت همیشه تضمین نمیشود (به
object.__del__()مراجعه کنید). اگر delete نادرست باشد، مقدار delete_on_close نادیده گرفته میشود.بنابراین برای استفاده از نام پرونده موقت جهت باز کردن مجدد پرونده پس از بستن آن، یا اطمینان حاصل کنید که پرونده هنگام بسته شدن حذف نشود (پارامتر delete را روی false تنظیم کنید) یا، در صورتی که پرونده موقت در یک دستور
withایجاد شده باشد، پارامتر delete_on_close را روی false تنظیم کنید. روش دوم توصیه میشود، زیرا به پاکسازی خودکار پرونده موقت هنگام خروج از مدیر زمینه کمک میکند.باز کردن دوبارهی پرونده موقت با نام آن، در حالی که هنوز باز است، بهصورت زیر عمل میکند:
در POSIX، همیشه میتوان پرونده را دوباره باز کرد.
در ویندوز، اطمینان حاصل کنید که حداقل یکی از شرایط زیر برقرار باشد:
delete نادرست است
باز کردن اضافی، دسترسی حذف را به اشتراک میگذارد (برای مثال با فراخوانی
os.open()با پرچمO_TEMPORARY)delete true است اما delete_on_close false است. توجه داشته باشید که در این حالت، باز شدنهای اضافی که دسترسی حذف را بهاشتراک نمیگذارند (برای مثال ایجادشده از طریق تابع توکار
open()) باید پیش از خروج از مدیر زمینه بسته شوند، در غیر این صورت فراخوانیos.unlink()هنگام خروج از مدیر زمینه باPermissionErrorناموفق خواهد شد.
در ویندوز، اگر delete_on_close برابر false باشد و پرونده در پوشهای ایجاد شود که کاربر دسترسی حذف به آن را ندارد، فراخوانی
os.unlink()هنگام خروج از مدیر زمینه باPermissionErrorشکست خواهد خورد. هنگامی که delete_on_close برابر true باشد، این حالت نمیتواند رخ دهد، زیرا دسترسی حذف توسط باز کردن پرونده درخواست میشود و اگر دسترسی درخواستشده اعطا نشود، باز کردن پرونده بلافاصله شکست میخورد.در POSIX (فقط)، فرایندی که بهطور ناگهانی با SIGKILL خاتمه یافته باشد، نمیتواند بهطور خودکار هیچیک از NamedTemporaryFileهایی را که ایجاد کرده است حذف کند.
یک رویداد حسابرسی
tempfile.mkstempرا با آرگومانfullpathپرتاب میکند.تغییر یافته در نسخهی 3.8: پارامتر errors اضافه شد.
تغییر یافته در نسخهی 3.12: پارامتر delete_on_close افزوده شد.
- class tempfile.SpooledTemporaryFile(max_size=0, mode='w+b', buffering=-1, encoding=None, newline=None, suffix=None, prefix=None, dir=None, *, errors=None)¶
این کلاس دقیقاً مانند
TemporaryFile()عمل میکند، با این تفاوت که دادهها بهصورت اسپول (spooled) در حافظه نگهداری میشوند تا زمانی که اندازه پرونده از max_size فراتر رود، یا تا زمانی که متدfileno()پرونده فراخوانی شود؛ در این نقطه محتوا روی دیسک نوشته میشود و عملیات مانندTemporaryFile()ادامه مییابد.- rollover()¶
پرونده حاصل یک متد اضافی دارد،
rollover()، که باعث میشود پرونده صرفنظر از اندازهاش به یک پرونده روی دیسک منتقل شود.
شیء برگرداندهشده یک شیء شبهپرونده است که ویژگی
_fileآن یا یک شیءio.BytesIOیاio.TextIOWrapperاست (بسته به اینکه حالت دودویی یا متنی تعیین شده باشد) یا یک شیء پرونده واقعی است، بسته به اینکهrollover()فراخوانی شده باشد. میتوان از این شیء شبهپرونده در یک دستورwithاستفاده کرد، درست مانند یک پرونده معمولی.تغییر یافته در نسخهی 3.3: متد truncate اکنون یک آرگومان size را میپذیرد.
تغییر یافته در نسخهی 3.8: پارامتر errors اضافه شد.
تغییر یافته در نسخهی 3.11: بهطور کامل کلاسهای پایه انتزاعی
io.BufferedIOBaseوio.TextIOBaseرا پیادهسازی میکند (بسته به اینکه حالت دودویی یا متنی مشخص شده باشد).
- class tempfile.TemporaryDirectory(suffix=None, prefix=None, dir=None, ignore_cleanup_errors=False, *, delete=True)¶
این کلاس با استفاده از همان قواعد
mkdtemp()، یک پوشه موقت را بهصورت امن ایجاد میکند. شیء حاصل میتواند بهعنوان یک context manager استفاده شود (به مثالها مراجعه کنید). پس از تکمیل زمینه یا تخریب شیء پوشه موقت، پوشه موقت تازهساختهشده و تمام محتویات آن از سیستم پرونده حذف میشوند.- name¶
نام پوشه را میتوان از ویژگی
nameشیء برگرداندهشده بازیابی کرد. هنگامی که شیء برگرداندهشده بهعنوان یک context manager استفاده شود،nameبه هدف عبارتasدر دستورwithاختصاص مییابد، در صورتی که وجود داشته باشد.
- cleanup()¶
پوشه را میتوان با فراخوانی متد
cleanup()بهصورت صریح پاکسازی کرد. اگر ignore_cleanup_errors درست باشد، تمام استثناهای مدیریتنشده در جریان پاکسازی صریح یا ضمنی (مانندPermissionErrorهنگام حذف پروندههای باز در ویندوز) نادیده گرفته خواهند شد و آیتمهای قابلحذف باقیمانده بر پایهی «بهترین تلاش» حذف خواهند شد. در غیر این صورت، خطاها در هر زمینهای که پاکسازی در آن رخ دهد پرتاب خواهند شد (فراخوانیcleanup()، خروج از مدیر زمینه، زمانی که شیء زبالهروبی میشود یا هنگام خاموش شدن مفسر).
میتوان از پارامتر delete برای غیرفعال کردن پاکسازی درخت پوشهها هنگام خروج از زمینه استفاده کرد. اگرچه ممکن است غیرعادی به نظر برسد که یک مدیر زمینه عملیات انجامشده هنگام خروج از زمینه را غیرفعال کند، اما این کار میتواند در حین اشکالزدایی یا زمانی که نیاز دارید رفتار پاکسازی شما بر اساس منطق دیگری مشروط باشد، مفید باشد.
یک رویداد حسابرسی
tempfile.mkdtempرا با آرگومانfullpathپرتاب میکند.اضافه شده در نسخهی 3.2.
تغییر یافته در نسخهی 3.10: پارامتر ignore_cleanup_errors افزوده شد.
تغییر یافته در نسخهی 3.12: پارامتر delete افزوده شد.
- tempfile.mkstemp(suffix=None, prefix=None, dir=None, text=False)¶
یک پرونده موقت را به امنترین شیوه ممکن ایجاد میکند. با فرض اینکه پلتفرم پرچم
os.O_EXCLرا برایos.open()بهدرستی پیادهسازی کرده باشد، هیچگونه شرایط رقابتی در ایجاد پرونده وجود ندارد. پرونده تنها توسط شناسه کاربر ایجادکننده قابل خواندن و نوشتن است. اگر پلتفرم از بیتهای دسترسی برای نشان دادن اینکه آیا یک پرونده قابل اجرا است یا خیر استفاده کند، این پرونده توسط هیچکس قابل اجرا نیست.توصیفگر پرونده توسط فرآیندهای فرزند به ارث برده نمیشود.
برخلاف
TemporaryFile()، کاربرmkstemp()مسئول بستن توصیفگر پرونده (برای مثال، با استفاده ازos.close()) و حذف پرونده موقت (برای مثال، با استفاده ازos.remove()) است.اگر suffix برابر
Noneنباشد، نام پرونده با آن پسوند پایان مییابد، در غیر این صورت پسوندی نخواهد داشت.mkstemp()بین نام پرونده و پسوند نقطه قرار نمیدهد؛ اگر به یک نقطه نیاز دارید، آن را در ابتدای suffix قرار دهید.اگر prefix برابر
Noneنباشد، نام پرونده با آن پیشوند آغاز میشود؛ در غیر این صورت، از یک پیشوند پیشفرض استفاده میشود. مقدار پیشفرض، بسته به مورد، مقدار بازگشتیgettempprefix()یاgettempprefixb()است.اگر dir برابر
Noneنباشد، پرونده در آن پوشه ایجاد میشود؛ در غیر این صورت، از یک پوشهی پیشفرض استفاده میشود. پوشهی پیشفرض از فهرستی وابسته به پلتفرم انتخاب میشود، اما کاربر برنامه میتواند محل پوشه را با تنظیم متغیرهای محیطی TMPDIR، TEMP یا TMP کنترل کند. بنابراین هیچ تضمینی وجود ندارد که نام پرونده تولیدشده دارای ویژگیهای مناسبی باشد، مانند اینکه هنگام ارسال به فرمانهای خارجی از طریقos.popen()نیازی به علامت نقلقول نداشته باشد.اگر هر یک از suffix، prefix و dir برابر
Noneنباشند، باید از یک نوع باشند. اگر آنها bytes باشند، نام بازگشتی به جای str از نوع bytes خواهد بود. اگر میخواهید با حفظ رفتار پیشفرض در سایر موارد، مقدار بازگشتی از نوع bytes را تحمیل کنید،suffix=b''را ارسال کنید.اگر text مشخص شده و درست باشد، پرونده در حالت متنی باز میشود. در غیر این صورت، پرونده (بهطور پیشفرض) در حالت دودویی باز میشود.
mkstemp()یک تاپل شامل یک دسته در سطح سیستمعامل برای یک پرونده باز (مانند آنچه توسطos.open()بازگردانده میشود) و نام مسیر مطلق آن پرونده را، به همین ترتیب، بازمیگرداند.یک رویداد حسابرسی
tempfile.mkstempرا با آرگومانfullpathپرتاب میکند.تغییر یافته در نسخهی 3.5: اکنون میتوان suffix، prefix و dir را بهصورت بایت ارائه کرد تا یک مقدار بازگشتی از نوع بایت به دست آید. پیش از این، فقط رشته (str) مجاز بود. suffix و prefix اکنون بهطور پیشفرض
Noneرا میپذیرند تا باعث استفاده از یک مقدار پیشفرض مناسب شوند.تغییر یافته در نسخهی 3.6: پارامتر dir اکنون path-like object را میپذیرد.
- tempfile.mkdtemp(suffix=None, prefix=None, dir=None)¶
یک پوشه موقت را به امنترین روش ممکن ایجاد میکند. در ایجاد پوشه هیچگونه شرایط رقابتی وجود ندارد. این پوشه فقط توسط شناسه کاربری ایجادکننده قابل خواندن، قابل نوشتن و قابل جستجو است.
کاربر
mkdtemp()مسئول حذف پوشه موقت و محتویات آن پس از اتمام کار با آن است.آرگومانهای prefix، suffix و dir همانند آرگومانهای
mkstemp()هستند.mkdtemp()مسیر مطلق پوشهی جدید را بازمیگرداند.یک رویداد حسابرسی
tempfile.mkdtempرا با آرگومانfullpathپرتاب میکند.تغییر یافته در نسخهی 3.5: اکنون میتوان suffix، prefix و dir را بهصورت بایت ارائه کرد تا یک مقدار بازگشتی از نوع بایت به دست آید. پیش از این، فقط رشته (str) مجاز بود. suffix و prefix اکنون بهطور پیشفرض
Noneرا میپذیرند تا باعث استفاده از یک مقدار پیشفرض مناسب شوند.تغییر یافته در نسخهی 3.6: پارامتر dir اکنون path-like object را میپذیرد.
تغییر یافته در نسخهی 3.12:
mkdtemp()اکنون همیشه یک مسیر مطلق را بازمیگرداند، حتی اگر dir نسبی باشد.
- tempfile.gettempdir()¶
نام پوشهای را که برای پروندههای موقت استفاده میشود، برمیگرداند. این، مقدار پیشفرض آرگومان dir برای همه توابع این ماژول را تعریف میکند.
پایتون فهرست استانداردی از پوشهها را جستجو میکند تا پوشهای را بیابد که کاربر فراخوان بتواند در آن پرونده ایجاد کند. این فهرست عبارت است از:
پوشهای که متغیر محیطی
TMPDIRنام آن را تعیین میکند.پوشهای که با متغیر محیطی
TEMPنامگذاری شده است.پوشهای که نام آن با متغیر محیطی
TMPمشخص شده است.یک مکان وابسته به سکو:
On Windows, the directories
%USERPROFILE%\AppData\Local\Temp,%SYSTEMROOT%\Temp,C:\TEMP,C:\TMP,\TEMP, and\TMP, in that order.در تمام سکوهای دیگر، پوشههای
/tmp،/var/tmpو/usr/tmp، به همین ترتیب.
بهعنوان آخرین راهحل، پوشهی کاری فعلی.
نتیجهی این جستجو در نهانگاه ذخیره میشود، شرح
tempdirرا در زیر ببینید.تغییر یافته در نسخهی 3.10: همیشه یک str برمیگرداند. پیش از این، هر مقدار
tempdirرا صرفنظر از نوع آن برمیگرداند، تا زمانی کهNoneنبود.
- tempfile.gettempdirb()¶
مانند
gettempdir()است، اما مقدار بازگشتی بهصورت بایت است.اضافه شده در نسخهی 3.5.
- tempfile.gettempprefix()¶
پیشوند نام پروندهای را که برای ایجاد پروندههای موقت استفاده میشود، برمیگرداند. این پیشوند شامل کامپوننت پوشه نمیشود.
- tempfile.gettempprefixb()¶
مشابه
gettempprefix()است، اما مقدار بازگشتی بهصورت بایت است.اضافه شده در نسخهی 3.5.
این ماژول از یک متغیر سراسری برای ذخیرهی نام پوشهی مورد استفاده برای پروندههای موقت استفاده میکند؛ نامی که توسط gettempdir() بازگردانده میشود. میتوان این متغیر را مستقیماً برای نادیده گرفتن فرآیند انتخاب تنظیم کرد، اما این کار توصیه نمیشود. همهی توابع این ماژول یک آرگومان dir میگیرند که میتوان از آن برای مشخص کردن پوشه استفاده کرد. این روش توصیهشدهای است که با تغییر رفتار سراسری API، سایر کدهای بیخبر را غافلگیر نمیکند.
- tempfile.tempdir¶
هنگامی که به مقداری غیر از
Noneتنظیم شود، این متغیر مقدار پیشفرض آرگومان dir برای توابع تعریفشده در این ماژول را، از جمله نوع آن (bytes یا str)، تعیین میکند. این مقدار نمیتواند یک path-like object باشد.اگر
tempdirدر هر فراخوانی از هر یک از توابع بالا به جزgettempprefix()برابرNoneباشد (پیشفرض)، طبق الگوریتم توصیفشده درgettempdir()مقداردهی اولیه میشود.توجه
مراقب باشید که اگر
tempdirرا روی مقداری از نوع bytes تنظیم کنید، عارضه جانبی ناخوشایندی وجود دارد: هنگامی که آرگومانهای صریحprefix،suffixیاdirاز نوع str ارائه نشده باشند، نوع بازگشتی پیشفرض سراسریmkstemp()وmkdtemp()به bytes تغییر میکند. لطفاً کدی ننویسید که این رفتار را انتظار دارد یا به آن وابسته است. این رفتار ناخوشایند برای سازگاری با پیادهسازی تاریخی حفظ شده است.
مثالها¶
در اینجا چند نمونه از کاربرد معمول ماژول tempfile آمده است:
>>> import tempfile
# create a temporary file and write some data to it
>>> fp = tempfile.TemporaryFile()
>>> fp.write(b'Hello world!')
# read data from file
>>> fp.seek(0)
>>> fp.read()
b'Hello world!'
# close the file, it will be removed
>>> fp.close()
# create a temporary file using a context manager
>>> with tempfile.TemporaryFile() as fp:
... fp.write(b'Hello world!')
... fp.seek(0)
... fp.read()
b'Hello world!'
>>>
# file is now closed and removed
# create a temporary file using a context manager
# close the file, use the name to open the file again
>>> with tempfile.NamedTemporaryFile(delete_on_close=False) as fp:
... fp.write(b'Hello world!')
... fp.close()
... # the file is closed, but not removed
... # open the file again by using its name
... with open(fp.name, mode='rb') as f:
... f.read()
b'Hello world!'
>>>
# file is now removed
# create a temporary directory using the context manager
>>> with tempfile.TemporaryDirectory() as tmpdirname:
... print('created temporary directory', tmpdirname)
>>>
# directory and contents have been removed
توابع و متغیرهای منسوخ¶
یک روش قدیمی برای ایجاد پروندههای موقت این بود که ابتدا یک نام پرونده با تابع mktemp() تولید شود و سپس پروندهای با استفاده از این نام ایجاد شود. متأسفانه این روش امن نیست، زیرا ممکن است فرایند دیگری در فاصله بین فراخوانی mktemp() و تلاش بعدی فرایند نخست برای ایجاد پرونده، پروندهای با همین نام ایجاد کند. راهحل این است که این دو مرحله با هم ترکیب شوند و پرونده بلافاصله ایجاد شود. این رویکرد در mkstemp() و سایر توابعی که در بالا توضیح داده شدهاند، به کار میرود.
- tempfile.mktemp(suffix='', prefix='tmp', dir=None)¶
منسوخ شده از نسخهی 2.3: بهجای آن از
mkstemp()استفاده کنید.مسیر مطلق پروندهای را برمیگرداند که در زمان انجام فراخوانی وجود نداشت. آرگومانهای prefix، suffix و dir مشابه آرگومانهای
mkstemp()هستند، با این تفاوت که از نام پروندههای بایتی،suffix=Noneوprefix=Noneپشتیبانی نمیشود.هشدار
استفاده از این تابع ممکن است یک حفرهی امنیتی در برنامهی شما ایجاد کند. تا بخواهید کاری با نام پروندهای که برمیگرداند انجام دهید، ممکن است شخص دیگری پیشدستی کرده باشد. میتوان استفاده از
mktemp()را بهراحتی باNamedTemporaryFile()جایگزین کرد و پارامترdelete=Falseرا به آن ارسال کرد:>>> f = NamedTemporaryFile(delete=False) >>> f.name '/tmp/tmptjujjt' >>> f.write(b"Hello World!\n") 13 >>> f.close() >>> os.unlink(f.name) >>> os.path.exists(f.name) False