وبلاگ رسانگار
با ما حرفه ای باشید

سرور مجازی NVMe

مدیران زمینه پایتون

0 3
زمان لازم برای مطالعه: 6 دقیقه


معرفی

یکی از مبهم ترین ویژگی های پایتون که تقریباً همه برنامه نویسان پایتون، حتی مبتدیان، از آن استفاده می کنند، اما واقعا نمی دانند، این است. مدیران زمینه. شما احتمالا آنها را در قالب دیده اید with عباراتی که معمولاً برای اولین بار در هنگام یادگیری باز کردن فایل ها در پایتون با آنها مواجه می شوند. اگرچه مدیران زمینه در ابتدا کمی عجیب به نظر می رسند، اما وقتی واقعاً در آنها غوطه ور می شویم، انگیزه و تکنیک های پشت آن را درک می کنیم، به یک سلاح جدید در زرادخانه برنامه نویسی خود دسترسی پیدا می کنیم. بنابراین بدون هیچ مقدمه ای، بیایید به آن شیرجه بزنیم!

انگیزه: مدیریت منابع

“نیاز مادر اختراع است”

برای اینکه واقعاً بفهمیم مدیر زمینه چیست و چگونه می‌توانیم از آن استفاده کنیم، ابتدا باید انگیزه‌های پشت آن را بررسی کنیم – ضرورت‌هایی که باعث ایجاد این “اختراع” شد.

انگیزه اصلی مدیران زمینه مدیریت منابع است. وقتی برنامه ای می خواهد به یک منبع دسترسی پیدا کند روی کامپیوتر، آن را از سیستم عامل درخواست می کند، و سیستم عامل نیز به نوبه خود، دسته ای برای آن منبع در اختیار آن قرار می دهد. برخی از نمونه های رایج این گونه منابع فایل ها و پورت های شبکه هستند. آنچه مهم است درک این است که این منابع در دسترس محدود هستند، به عنوان مثال، یک پورت شبکه می تواند توسط یک واحد استفاده شود. process در یک زمان، و تعداد محدودی پورت در دسترس است. بنابراین هر زمان که ما باز کن یک منبع، ما باید به یاد داشته باشیم بستن آن را، به طوری که منبع آزاد شود. اما متأسفانه گفتن آن آسان تر از انجام آن است.

ساده ترین راه برای انجام مدیریت منابع مناسب فراخوانی است close عملکرد پس از اتمام کار با منبع:

opened_file = open('readme.txt')
text = opened_file.read()
...
opened_file.close()

در اینجا ما در حال باز کردن فایلی به نام هستیم readme.txt، خواندن فایل و ذخیره محتوای آن در یک رشته textو پس از اتمام کار، فایل را با فراخوانی ببندید close() روش از opened_file هدف – شی. اکنون در نگاه اول ممکن است به نظر خوب برسد، اما در واقع، اصلا قوی نیست. اگر هر چیزی بین باز کردن فایل و بستن فایل اتفاقی غیرمنتظره رخ می‌دهد که باعث می‌شود برنامه در اجرای خط حاوی close بیانیه، نشت منبع وجود خواهد داشت. اینها حوادث غیر منتظره چیزی هستند که ما به آن می گوییم exceptionsیک مورد معمول زمانی است که شخصی برنامه را در حین اجرا به زور می بندد.

در حال حاضر، راه مناسب برای رسیدگی به این خواهد بود استفاده از رسیدگی به استثنا، استفاده کردن try...else بلوک ها:

try:
    opened_file = open('readme.txt')
    text = opened_file.read()
    
else:
    opened_file.close()

پایتون همیشه از کد موجود در else بلوک بدون توجه به هر اتفاقی که ممکن است رخ دهد اجرا می شود. این روشی است که برنامه نویسان زبان های دیگر مدیریت منابع را مدیریت می کنند، اما برنامه نویسان پایتون مکانیسم خاصی را دریافت می کنند که به آنها امکان می دهد همان عملکرد را بدون نیاز به تمام دیگ بخار اجرا کنند. اینجاست که مدیران زمینه وارد بازی می شوند!

پیشنهاد می‌کنیم بخوانید:  ورود به دنیای همزمانی با پایتون

پیاده سازی مدیران زمینه

اکنون که ما با مهمترین بخش در مورد درک مدیران زمینه تمام شده ایم، می توانیم به اجرای آنها بپریم. برای این آموزش یک سفارشی پیاده سازی می کنیم File کلاس این کاملاً زائد است زیرا پایتون قبلاً این را ارائه کرده است، اما با این وجود، تمرین یادگیری خوبی خواهد بود زیرا ما همیشه می‌توانیم با آن ارتباط برقرار کنیم. File کلاسی که قبلاً در کتابخانه استاندارد وجود دارد.

روش استاندارد و «سطح پایین» برای پیاده‌سازی مدیر زمینه، تعریف دو روش «جادویی» در کلاسی است که می‌خواهید مدیریت منابع را برای آن پیاده‌سازی کنید. __enter__و __exit__. اگر در حال گمراه شدن هستید، “این روش جادویی چیست؟ من قبلاً چنین چیزی نشنیده ام” – خوب، اگر برنامه نویسی شی گرا را در پایتون شروع کرده اید، مطمئناً قبلاً با یک روش جادویی روبرو شده اید. روش __init__.

به دلیل نبود کلمات بهتر، آنها روش های خاصی هستند که می توانید برای هوشمندتر کردن کلاس های خود تعریف کنید یا “جادو” را به آنها اضافه کنید. شما می توانید یک لیست مرجع خوب از تمام روش های جادویی موجود در پایتون پیدا کنید اینجا.

به هر حال، برای بازگشت به موضوع، قبل از شروع اجرای این دو روش جادویی، باید هدف آنها را درک کنیم. __enter__ روشی است که هنگام باز کردن منبع، یا به بیان کمی فنی تر، فراخوانی می شود – زمانی که ما “ورود” می کنیم زمینه زمان اجرا. این with عبارت مقدار برگشتی این روش را به هدف مشخص شده در as بند بیانیه:

class FileManager:
    def __init__(self, filename):
        self.filename = filename
        
    def __enter__(self):
        self.opened_file = open(self.filename)
        return self.opened_file

همانطور که می بینید، __enter__ روش باز کردن منبع – فایل و برگرداندن آن است. وقتی از این استفاده می کنیم FileManager در یک with عبارت، این متد فراخوانی می شود و مقدار بازگشتی آن به متغیر هدفی که در آن ذکر کردید متصل می شود as عبارت:

with FileManager('readme.txt') as file:
    text = file.read()

بیایید قسمت به قسمت آن را تجزیه کنیم. اولا، یک نمونه از FileManager کلاس زمانی ایجاد می شود که ما آن را نمونه سازی می کنیم و نام فایل را ارسال می کنیم "readme.txt" به سازنده سپس with بیانیه شروع به کار می کند روی آن را صدا می کند __enter__ روش آن FileManager شی و مقدار برگشتی را به file متغیر ذکر شده در as عبارت. سپس، در داخل with بلاک، ما می توانیم هر کاری که می خواهیم با منبع باز شده انجام دهیم.

بخش مهم دیگر پازل این است __exit__ روش. این __exit__ متد حاوی کد پاکسازی است که باید پس از اتمام کار با منبع اجرا شود. دستورالعمل های این روش مشابه دستورالعمل های موجود در این روش خواهد بود else بلوکی که قبلاً در مورد رسیدگی به استثناء بحث کردیم. برای تکرار، __exit__ روش شامل دستورالعمل هایی برای بستن صحیح کنترل کننده منبع است، به طوری که منبع برای استفاده بیشتر توسط برنامه های دیگر در سیستم عامل آزاد می شود.

حالا بیایید نگاهی به روش نوشتن این روش بیندازیم:

class FileManager:
    def __exit__(self. *exc):
        self.opened_file.close()

هر زمان که از نمونه های این کلاس در a استفاده شود with بیانیه، این __exit__ قبل از خروج برنامه از متد فراخوانی می شود with مسدود کردن، یا قبل از توقف برنامه به دلیل برخی استثناها. حالا بیایید به کل نگاه کنیم FileManager کلاس تا ما یک ایده کامل داشته باشیم:

class FileManager:
    def __init__(self, filename):
        self.filename = filename
        
    def __enter__(self):
        self.opened_file = open(self.filename)
        return self.opened_file
    
    def __exit__(self, *exc):
        self.opened_file.close()

به اندازه کافی ساده، درست است؟ ما فقط عملیات باز کردن و پاکسازی را در متدهای جادویی مربوطه تعریف کردیم، و پایتون مدیریت منابع را در هر کجا که ممکن است از این کلاس استفاده شود، انجام خواهد داد. این ما را به موضوع بعدی می‌رساند، روش‌های مختلفی که می‌توانیم از کلاس‌های مدیریت متن استفاده کنیم، مانند این FileManager کلاس

پیشنهاد می‌کنیم بخوانید:  هیچ ماژولی با نام 'mysql"" در پایتون

استفاده از Context Managers

در اینجا چیز زیادی برای توضیح وجود ندارد، بنابراین به جای نوشتن پاراگراف های طولانی، اجازه دهید نگاهی به چند قطعه کد در این بخش بیندازیم:

file = FileManager('readme.txt')
with file as managed_file:
    text = managed_file.read()
    print(text)
with FileManager('readme.txt') as managed_file:
    text = managed_file.read()
    print(text)
def open_file(filename):
    file = FileManager(filename)
    return file

with open_file('readme.txt') as managed_file:
    text = managed_file.read()
    print(text)

می توانید ببینید که نکته کلیدی که باید به خاطر بسپارید این است که

  1. شیء به with بیانیه باید داشته باشد __enter__ و __exit__ مواد و روش ها.
  2. این __enter__ متد باید منبعی را که قرار است در آن استفاده شود برگرداند with مسدود کردن.

مهم: نکات ظریفی وجود دارد که من از آن صرف نظر کردم تا بحث را به نقطه اصلی تبدیل کنم. برای مشخصات دقیق این روش های جادویی، به مستندات پایتون مراجعه کنید اینجا.

استفاده کردن _contextlib_

این ذن پایتون – اصل راهنمای پایتون به عنوان فهرستی از کلمات قصار – بیان می کند:

“ساده بهتر از پیچیده است”

برای اینکه واقعاً این نقطه را به خانه هدایت کند، توسعه دهندگان پایتون کتابخانه ای به نام ایجاد کرده اند contextlib حاوی ابزارهای مفید در مورد مدیران زمینه، گویی که مشکل مدیریت منابع را به اندازه کافی ساده نکرده اند. ما در اینجا تنها یکی از آنها را به طور خلاصه نشان می دهیم، اما توصیه می کنیم برای اطلاعات بیشتر، اسناد رسمی پایتون را بررسی کنید.

from contextlib import contextmanager

@contextmanager
def open_file(filename):
    opened_file = open(filename)
    try:
        yield opened_file
    finally:
        opened_file.close()

مانند کد بالا، ما به سادگی می توانیم تابعی را تعریف کنیم که yieldمنبع حفاظت شده در a try بیانیه، بسته شدن آن در بعد finally بیانیه. راه دیگری برای درک آن:

  • تمام مطالبی که در غیر این صورت در آن قرار می دادید __enter__ روش، به جز return بیانیه، قبل از try اینجا را مسدود کنید – اساساً دستورالعمل باز کردن منبع.
  • به جای برگرداندن منبع، شما yield آن، داخل a try مسدود کردن.
  • محتویات __exit__ روش به داخل مربوطه می رود finally مسدود کردن.

وقتی چنین عملکردی داشتیم، می توانیم با استفاده از آن آن را تزئین کنیم contextlib.contextmanager دکوراتور و ما خوب هستیم:

with open_file('readme.txt') as managed_file:
    text = managed_file.read()
    print(text)

همانطور که می بینید، تزئین شده است open_file تابع یک مدیر زمینه را برمی گرداند و ما می توانیم مستقیماً از آن استفاده کنیم. این به ما امکان می‌دهد به همان اثری که ایجاد می‌کنیم دست پیدا کنیم FileManager کلاس، بدون هیچ زحمتی.

نتیجه

اگر مشتاق هستید و می خواهید درباره مدیران زمینه بیشتر بخوانید، توصیه می کنم پیوندهای زیر را بررسی کنید:

(برچسب‌ها به ترجمه)# python



منتشر شده در 1403-01-25 09:38:06

امتیاز شما به این مطلب
دیدگاه شما در خصوص مطلب چیست ؟

آدرس ایمیل شما منتشر نخواهد شد.

لطفا دیدگاه خود را با احترام به دیدگاه های دیگران و با توجه به محتوای مطلب درج کنید