سطح مقدماتی (Beginner Level)
احتمالا بارها دیدهاید که برنامهنویسان پایتون کدهای خود را داخل یک شرط عجیب به نام if __name__ == "__main__": قرار میدهند. برای درک این موضوع، ابتدا باید بدانیم پایتون چگونه فایلها را اجرا میکند.
در پایتون، هر فایلی که اجرا میکنید، دارای یک متغیر مخفی و داخلی به نام __name__ است. مقدار این متغیر بسته به نحوه اجرای فایل تغییر میکند.
۱. متغیر __name__ چیست؟
وقتی شما یک فایل پایتون را مستقیماً اجرا میکنید (مثلاً روی دکمه Run کلیک میکنید یا دستور python file.py را میزنید)، پایتون نام آن فایل را به صورت پیشفرض برابر با "__main__" قرار میدهد.
اما اگر همین فایل را درون یک فایل دیگر import کنید، مقدار __name__ برابر با نام فایل (بدون .py) خواهد بود.
مثال اول: بررسی مقدار __name__
این کد را اجرا کنید تا ببینید متغیر __name__ در حال حاضر چه مقداری دارد.
۲. چرا از این شرط استفاده میکنیم؟
هدف اصلی این است که قطعه کدی بنویسیم که فقط وقتی فایل مستقیماً اجرا شد کار کند، اما اگر کسی فایل ما را import کرد تا از توابع آن استفاده کند، کدهای اجرایی ما مزاحم او نشوند.
فرض کنید یک فایل ابزار دارید که توابع ریاضی دارد. اگر درون آن فایل print() نوشته باشید، هر کسی که فایل شما را ایمپورت کند، ناخواسته آن پرینت را در خروجی خود میبیند.
مثال دوم: ساختار صحیح یک اسکریپت
در این روش، تعریف توابع همیشه انجام میشود، اما اجرای آنها (فراخوانی تابع main) فقط زمانی رخ میدهد که فایل مستقیماً اجرا شود.
سطح پیشرفته (Professional Level)
در سطح حرفهای، استفاده از این الگو فراتر از صرفاً جلوگیری از اجرای کد است. این الگو برای تستنویسی، مالتیپراسسینگ و ساخت ابزارهای خط فرمان (CLI) حیاتی است.
۱. جلوگیری از Side Effects در زمان Import
وقتی مفسر پایتون به دستور import module میرسد، تمام کدهای سطح بالای (Top-level) آن ماژول را بلافاصله اجرا میکند. اگر کدهای سنگین یا خروجیدار خارج از بلوک if __name__ ... باشند، به محض ایمپورت شدن، اجرا میشوند که به آن Side Effect میگویند.
بیایید تفاوت را ببینیم (این کدها استاتیک هستند چون نیاز به دو فایل مجزا دارند):
# Static: bad_module.py (Without protection)
print("Loading heavy model...") # This runs immediately on import!
def predict():
pass
# Static: good_module.py (With protection)
def predict():
pass
if __name__ == "__main__":
print("Running tests or examples...") # Only runs if executed directly
۲. اهمیت در Multiprocessing
اگر در ویندوز از ماژول multiprocessing استفاده میکنید، استفاده از این گارد الزامی است.
وقتی پایتون در ویندوز یک پروسه جدید (Child Process) میسازد، در واقع اسکریپت اصلی را دوباره ایمپورت میکند. اگر این شرط وجود نداشته باشد، پروسه فرزند دوباره تلاش میکند پروسههای فرزند دیگری بسازد و سیستم وارد یک حلقه بینهایت (Infinite Loop) شده و کرش میکند.
مثال سوم: اجرای امن در پردازش موازی
۳. تست واحد (Unit Testing)
این ساختار به شما اجازه میدهد انتهای فایل خود کدهای تست سریع بنویسید. وقتی فایل را مستقیماً اجرا میکنید، تستها اجرا میشوند تا از صحت عملکرد مطمئن شوید. اما وقتی فایل را در فریمورکهای تست مثل pytest ایمپورت میکنید، آن تستهای دستی اجرا نمیشوند و تداخلی ایجاد نمیکنند.