ما معنى if __name__ == "__main__" في بايثون؟ شرح __name__ وmain مع أمثلة عملية

ما معنى if __name__ == __main__ في بايثون

إذا فتحت مشروع بايثون متوسطًا أو كبيرًا، فمن المحتمل أن تجد في آخر الملف هذا السطر:

if __name__ == "__main__":
    main()

كثير من المبتدئين ينسخونه كما هو دون أن يعرفوا لماذا نستخدمه، أو يظنون أن كلمة main إلزامية في كل برنامج بايثون كما في بعض لغات البرمجة الأخرى. الحقيقة أبسط: بايثون تعطي كل Module متغيرًا خاصًا اسمه __name__، وتتغير قيمته حسب الطريقة التي شغّلت بها الملف.

إذا شغلت ملف بايثون مباشرة، تكون قيمة __name__ هي "__main__". أما إذا استوردت الملف باستخدام import، فتكون قيمة __name__ هي اسم الـModule. لهذا نستطيع استخدام الشرط if __name__ == "__main__" لتنفيذ جزء من الكود عند التشغيل المباشر فقط، ومنعه من العمل تلقائيًا عند استيراد الملف.

في هذا الدرس العام من بايثون العرب سنشرح معنى __name__ و__main__ خطوة بخطوة، وسنرى الفرق بين تشغيل الملف واستيراده، ولماذا نستخدم دالة main()، وما معنى Main Guard، ومتى تحتاج هذا النمط فعلًا.

{alertInfo} الإجابة المختصرة: الشرط if __name__ == "__main__": يسمح لك بتنفيذ كود معين فقط عندما تشغّل الملف مباشرة، وعدم تنفيذه عندما يتم استيراد الملف كـModule داخل ملف آخر.

{getToc} $title={محتوى المقال}

ما هو __name__ في بايثون؟

__name__ اسم خاص توفره بايثون داخل كل Module. يمكنك طباعته مباشرة:

print(__name__)

لكن النتيجة تعتمد على طريقة تشغيل الملف.

الحالة الأولى: تشغيل الملف مباشرة

أنشئ ملفًا باسم:

app.py

واكتب داخله:

print(__name__)

ثم شغله:

python app.py

الناتج:

__main__

عندما يكون الملف هو نقطة البداية التي شغلت البرنامج منها، تعطيه بايثون الاسم الخاص __main__.

الحالة الثانية: استيراد الملف باستخدام import

لنفترض أن لدينا نفس الملف:

# app.py

print(__name__)

وأنشأنا ملفًا آخر:

# start.py

import app

الآن شغّل:

python start.py

سيطبع ملف app.py:

app

السبب أن app.py لم يعد الملف الأعلى الذي بدأ منه البرنامج، بل أصبح Module تم استيراده. لذلك أصبحت قيمة __name__ فيه هي اسم الـModule: "app".

الفرق بين تشغيل ملف بايثون مباشرة واستيراده باستخدام import

جدول يوضح الفكرة بسرعة

طريقة استخدام الملف قيمة __name__ داخل الملف
python app.py "__main__"
import app "app"
استيراد Module داخل Package اسم Module وقد يتضمن مسار Package.

إذن ما معنى if __name__ == "__main__"؟

الشرط:

if __name__ == "__main__":
    print("Run directly")

يعني:

إذا كان هذا الملف هو نقطة تشغيل البرنامج، نفّذ الكود الموجود داخل الشرط.

أما إذا تم استيراد الملف كـModule، فلن يتحقق الشرط.

مثال عملي بسيط

def greet(name):
    return f"Hello, {name}"


if __name__ == "__main__":
    print(
        greet("Ali")
    )

إذا شغلت الملف مباشرة:

python app.py

سيظهر:

Hello, Ali

لكن إذا استوردته:

import app

print(
    app.greet("Sara")
)

لن ينفذ greet("Ali") تلقائيًا. ستصبح الدالة متاحة للاستعمال فقط.

لماذا هذا مهم عند import؟

عند استيراد Module، تنفذ بايثون التعليمات الموجودة في المستوى الأعلى من الملف أثناء تهيئة الـModule.

تخيل هذا الملف:

# tools.py

def add(a, b):
    return a + b


print("Starting program...")

name = input(
    "Enter your name: "
)

print(
    add(5, 3)
)

إذا كتبت في ملف آخر:

import tools

فسينفذ print() وinput() أثناء الاستيراد، رغم أنك ربما أردت فقط استخدام add().

الحل باستخدام Main Guard

نضع كود التشغيل داخل الشرط:

# tools.py

def add(a, b):
    return a + b


if __name__ == "__main__":
    print(
        "Starting program..."
    )

    name = input(
        "Enter your name: "
    )

    print(
        add(5, 3)
    )

الآن:

import tools

print(
    tools.add(10, 20)
)

يستورد الدالة بدون تشغيل واجهة البرنامج التفاعلية.

منع تنفيذ الكود عند import باستخدام if __name__ == __main__

ما معنى Main Guard؟

يستخدم كثير من المبرمجين اسم Main Guard للإشارة إلى هذا الشرط:

if __name__ == "__main__":
    ...

فكر فيه كبوابة تمنع كود التشغيل الرئيسي من العمل عندما يُستخدم الملف كـModule مستورد.

هل يجب أن تكون هناك دالة اسمها main؟

لا. بايثون لا تفرض عليك دالة باسم main().

هذا صحيح:

if __name__ == "__main__":
    print("Hello")

وهذا صحيح أيضًا:

def start_program():
    print("Hello")


if __name__ == "__main__":
    start_program()

لكن الاسم main اتفاقية شائعة وواضحة للدالة التي تمثل نقطة تشغيل البرنامج.

لماذا يفضل وضع الكود داخل main()؟

بدل كتابة عشرات الأسطر مباشرة داخل Main Guard، من الأفضل غالبًا تنظيمها في دالة:

def main():
    print("Starting...")
    print("Loading data...")
    print("Running program...")


if __name__ == "__main__":
    main()

هذا يجعل:

  • الكود أسهل في القراءة.
  • المتغيرات داخل main() محلية بدل أن تصبح Global بلا حاجة.
  • اختبار أجزاء البرنامج أسهل.
  • إعادة استخدام الدوال من ملفات أخرى أسهل.
تنظيم برنامج بايثون باستخدام main function

الترتيب المقترح لملف بايثون

# 1. Imports
from pathlib import Path


# 2. Constants
DATA_FILE = Path("data.txt")


# 3. Functions / Classes
def load_data():
    return []


def process_data(data):
    return data


# 4. Main function
def main():
    data = load_data()
    result = process_data(data)

    print(result)


# 5. Entry point
if __name__ == "__main__":
    main()

ليس هذا قانونًا إلزاميًا لكل ملف، لكنه تنظيم واضح وشائع للبرامج الصغيرة والمتوسطة.

مثال عملي: آلة حاسبة قابلة للاستيراد والتشغيل

لدينا ملف:

# calculator.py

def add(a, b):
    return a + b


def subtract(a, b):
    return a - b


def main():
    first = float(
        input("First number: ")
    )

    second = float(
        input("Second number: ")
    )

    print(
        "Sum:",
        add(first, second)
    )


if __name__ == "__main__":
    main()

يمكن تشغيله كبرنامج:

python calculator.py

وفي الوقت نفسه يمكن استيراده:

from calculator import add


print(
    add(10, 5)
)

وفي هذه الحالة لن تظهر أسئلة input() لأن main() لم تُستدعَ.

ماذا يحدث فعليًا عند import؟

عندما تكتب:

import calculator

تقوم بايثون بتحميل Module وتنفيذ تعريفاتها وتعليماتها في المستوى الأعلى. تعريف Function نفسه لا يعني تنفيذ جسم Function.

مثل:

def add(a, b):
    return a + b

يتم إنشاء Function، لكن السطر داخلها لا يعمل حتى تستدعي:

add(1, 2)

وهذا سبب آخر يجعل وضع منطق البرنامج داخل Functions مفيدًا.

ما هو Top-level Code؟

Top-level Code هو الكود الموجود مباشرة في Module، وليس داخل Function أو Class.

في هذا المثال:

print("A")


def hello():
    print("B")


print("C")

السطران اللذان يطبعان A وC من Top-level Code، ولذلك يعملان عند تحميل Module. أما print("B") فلا يعمل حتى تستدعي hello().

ماذا تعني __main__ بالضبط؟

__main__ هو الاسم الخاص لبيئة التنفيذ الأعلى التي يبدأ منها برنامج بايثون. إذا شغلت:

python app.py

فسيعمل app.py كـTop-level Module، وتكون قيمة __name__ فيه:

"__main__"

هل __name__ متغير عادي أنشأته بنفسي؟

لا. بايثون توفره ضمن Module namespace. يمكنك قراءته مباشرة دون تعريفه:

print(__name__)

لكن لا يوجد سبب طبيعي لأن تعيد تعيينه يدويًا.

لماذا فيه شرطتان سفليتان؟

الأسماء التي تبدأ وتنتهي بشرطتين سفليتين تستخدمها بايثون للعديد من الأسماء الخاصة، مثل:

__name__
__file__
__package__
__init__
__repr__

لا تختصر __name__ إلى _name_. الشرطتان جزء من الاسم نفسه.

خطأ شائع: كتابة _name_ بدل __name__

هذا خاطئ:

if _name_ == "_main_":
    main()

الصحيح:

if __name__ == "__main__":
    main()

خطأ شائع: كتابة "main" بدل "__main__"

هذا لن يحقق المقارنة المطلوبة:

if __name__ == "main":
    main()

القيمة الخاصة هي:

"__main__"

خطأ شائع: نسيان النقطتين

الصحيح:

if __name__ == "__main__":
    main()

يجب أن ينتهي سطر if بعلامة :.

خطأ شائع: main بدون أقواس

هذا يشير إلى Function لكنه لا ينفذها:

if __name__ == "__main__":
    main

للتنفيذ:

if __name__ == "__main__":
    main()

خطأ شائع: وضع كل البرنامج داخل الشرط

هذا يعمل:

if __name__ == "__main__":
    name = input("Name: ")
    age = int(input("Age: "))

    print(name, age)

    # عشرات الأسطر الأخرى...

لكن عندما يكبر البرنامج، الأفضل تنظيمه داخل Functions:

def main():
    name = input("Name: ")
    age = int(input("Age: "))

    print(name, age)


if __name__ == "__main__":
    main()
أخطاء شائعة في if __name__ == __main__ في بايثون

هل الشرط يمنع استيراد الدوال؟

لا. الدوال المعرفة خارج الشرط تبقى قابلة للاستيراد:

def multiply(a, b):
    return a * b


if __name__ == "__main__":
    print(
        multiply(4, 5)
    )

يمكن لملف آخر كتابة:

from tools import multiply


print(
    multiply(10, 3)
)

هل الكود داخل if يصبح غير قابل للاستيراد؟

التعليمات داخل الشرط لا تنفذ عند Import لأن الشرط يكون False في ذلك Module. لكن الأسماء التي لا يتم إنشاؤها إلا داخل هذا الشرط قد لا تكون موجودة بعد الاستيراد.

لهذا لا تضع تعريفات Functions التي تريد إعادة استخدامها داخل Main Guard عادةً.

مثال تصميم غير جيد

if __name__ == "__main__":
    def add(a, b):
        return a + b

    print(
        add(1, 2)
    )

إذا أردت استيراد add من ملف آخر، لن تكون قد عُرّفت عند Import.

التصميم الأفضل

def add(a, b):
    return a + b


def main():
    print(
        add(1, 2)
    )


if __name__ == "__main__":
    main()

هل نحتاج Main Guard في كل ملف؟

لا. إذا كان الملف مجرد Module يحتوي Functions وClasses ولا يحتوي كود تشغيل مباشر، فلا تحتاج إلى إضافة الشرط لمجرد التقليد.

مثال Module بسيط:

# math_tools.py

def add(a, b):
    return a + b


def subtract(a, b):
    return a - b

لا يوجد كود يحتاج الحماية عند Import.

متى نستخدم if __name__ == "__main__"؟

استخدمه عندما يكون الملف يؤدي دورين أو يمكن أن يؤديهما:

  • يمكن تشغيله كبرنامج مستقل.
  • ويمكن استيراد Functions أو Classes منه.

أو عندما تريد منع Demo/Test/CLI Code من العمل عند الاستيراد.

مثال Demo داخل Module

def celsius_to_fahrenheit(c):
    return (c * 9 / 5) + 32


if __name__ == "__main__":
    print(
        celsius_to_fahrenheit(25)
    )

إذا شغلت الملف مباشرة تحصل على Demo سريع، وإذا استوردته تحصل على Function فقط.

لكن هل نضع الاختبارات الحقيقية داخل Main Guard؟

للتجارب الصغيرة قد ترى أمثلة داخل الشرط، لكن المشاريع الجادة تستفيد أكثر من ملفات اختبارات مستقلة باستخدام unittest أو pytest.

الـMain Guard ليس بديلًا عن نظام الاختبارات.

العلاقة بين main() وCLI

برامج سطر الأوامر تستخدم هذا النمط كثيرًا:

import argparse


def main():
    parser = argparse.ArgumentParser()

    parser.add_argument(
        "--name"
    )

    args = parser.parse_args()

    print(
        f"Hello {args.name}"
    )


if __name__ == "__main__":
    main()

فكود قراءة Arguments يخص تشغيل البرنامج نفسه، ولا نريد تنفيذه تلقائيًا لمجرد استيراد Module في اختبار أو ملف آخر.

العلاقة مع الاختبارات

لنفترض أن:

# app.py

def calculate_total(
    price,
    quantity
):
    return price * quantity


def main():
    print(
        calculate_total(
            10,
            3
        )
    )


if __name__ == "__main__":
    main()

يستطيع ملف الاختبار استيراد Function:

from app import calculate_total


def test_total():
    assert (
        calculate_total(10, 3)
        == 30
    )

ولا تعمل main() أثناء الاستيراد. هذه إحدى فوائد فصل منطق البرنامج عن نقطة التشغيل.

ماذا يحدث إذا حذفت Main Guard؟

إذا كتبت:

def main():
    print("Program started")


main()

فإن main() ستعمل سواء شغلت الملف مباشرة أو استوردته، لأن الاستدعاء موجود في Top-level Code.

هل import يشغل الملف مرة كاملة؟

عند أول استيراد للـModule في عملية بايثون، يتم تنفيذ Top-level Code لتهيئة الـModule. بعد ذلك تستخدم بايثون نظام Modules المحملة بدل إعادة تنفيذ الـModule بالطريقة البسيطة نفسها مع كل import متكرر داخل العملية.

لكن لا تعتمد على Import كطريقة لتشغيل أعمال جانبية. اجعل Functions وClasses واضحة، واستدعِ ما تحتاجه صراحة.

ماذا عن python -m؟

يمكن تشغيل Module باستخدام:

python -m module_name

عندما يكون Module هو نقطة التشغيل العليا بهذه الطريقة، يعمل ضمن بيئة __main__ أيضًا، ولذلك يتحقق Main Guard.

مثال بسيط

إذا كان لديك Module قابل للتشغيل كـModule، قد تكتب:

def main():
    print("Running module")


if __name__ == "__main__":
    main()

ثم تشغله بطريقة مناسبة لبنية المشروع باستخدام python -m ....

ما هو __main__.py؟

هذا مفهوم مرتبط لكنه ليس هو نفسه شرط __name__. يمكن أن تحتوي Package على ملف اسمه:

__main__.py

ليكون نقطة تشغيل عندما تستخدم:

python -m package_name

هذا مفيد للحزم القابلة للتشغيل، لكنه موضوع أعمق قليلًا من Main Guard البسيط.

هل __main__.py إلزامي لكل مشروع؟

لا. غالبية ملفات بايثون العادية لا تحتاجه. استخدمه عندما تصمم Package تريد تشغيلها عبر python -m package_name.

ما الفرق بين main.py و__main__.py؟

الملف المعنى
main.py اسم عادي يختاره المطور لملف رئيسي؛ لا يحمل سلوكًا خاصًا لمجرد اسمه.
__main__.py اسم خاص داخل Package يمكن استخدامه كنقطة تشغيل مع python -m package.

هل اسم الملف يجب أن يكون main.py؟

لا. يمكنك أن تسميه:

app.py
run.py
cli.py
server.py
program.py

الاسم main.py مجرد اختيار تنظيمي شائع.

هل وجود def main() يجعل الملف الرئيسي تلقائيًا؟

لا. هذه Function عادية:

def main():
    print("Hello")

لن تعمل حتى تستدعيها:

main()

أو تضع الاستدعاء تحت Main Guard.

هل if __name__ == "__main__" يزيد سرعة البرنامج؟

ليس هدفه تحسين الأداء. الهدف الأساسي التحكم فيما يعمل عندما يكون الملف نقطة دخول، وما يبقى مجرد تعريفات قابلة للاستيراد.

هل الشرط لأسباب أمنية؟

لا. هو ليس آلية حماية أمنية، ولا يمنع شخصًا من استدعاء Functions أو تشغيل الكود. هو مجرد آلية تنظيم وتحكم في طريقة تنفيذ Module.

مثال مشروع من ملفين

الهيكل:

project/
├── calculations.py
└── app.py

داخل calculations.py:

def calculate_discount(
    price,
    percent
):
    return (
        price
        * percent
        / 100
    )


if __name__ == "__main__":
    print(
        calculate_discount(
            100,
            10
        )
    )

داخل app.py:

from calculations import (
    calculate_discount
)


price = 200

discount = calculate_discount(
    price,
    15
)

print(discount)

عند تشغيل app.py لن يعمل Demo الموجود داخل Main Guard في calculations.py.

مثال أوضح: برنامج مهام

def add_task(tasks, text):
    tasks.append(text)


def show_tasks(tasks):
    for index, task in enumerate(
        tasks,
        start=1
    ):
        print(
            index,
            task
        )


def main():
    tasks = []

    add_task(
        tasks,
        "Learn Python"
    )

    add_task(
        tasks,
        "Build project"
    )

    show_tasks(tasks)


if __name__ == "__main__":
    main()

يمكن لاحقًا نقل add_task وshow_tasks إلى اختبارات أو Modules أخرى بسهولة.

هل من الأفضل أن تُرجع main() قيمة؟

في البرامج الصغيرة ليس ضروريًا. لكن بعض برامج CLI تجعل main() تعيد Exit Code، ثم تستخدم sys.exit().

import sys


def main():
    print("Done")

    return 0


if __name__ == "__main__":
    sys.exit(
        main()
    )

القيمة 0 تستخدم عادةً للدلالة على نجاح البرنامج على مستوى نظام التشغيل.

هل يجب استخدام sys.exit(main()) دائمًا؟

لا. إذا لم تكن تبني CLI يحتاج Exit Codes، فهذه الصيغة البسيطة ممتازة:

if __name__ == "__main__":
    main()

لماذا توصي بايثون بتقليل الكود داخل Main Guard؟

من الأفضل أن يحتوي الشرط على استدعاء بسيط مثل:

if __name__ == "__main__":
    main()

بدل إنشاء متغيرات كثيرة في المستوى العام. هذا يجعل المنطق داخل Function، والمتغيرات محلية، والاختبار وإعادة الاستخدام أسهل.

كيف أرى قيمة __name__ بنفسي؟

استخدم تجربة بملفين.

first.py:

print(
    "first:",
    __name__
)

second.py:

import first

print(
    "second:",
    __name__
)

عندما تشغل:

python second.py

سترى فكرة قريبة من:

first: first
second: __main__

لأن second.py هو نقطة التشغيل، بينما first.py تم استيراده.

هذه التجربة تلخص الموضوع كله

الملف الذي يبدأ منه البرنامج يرى نفسه باسم:

__main__

أما Modules التي يتم استيرادها فترى __name__ كاسم Module الخاص بها.

أخطاء مفاهيمية شائعة

الفكرة الخاطئة الصحيح
كل برنامج بايثون يجب أن يحتوي main(). لا، لكنها اتفاقية مفيدة.
اسم الملف يجب أن يكون main.py. لا، يمكن اختيار أي اسم مناسب.
Main Guard يمنع Import. لا، يمنع فقط تنفيذ الكود الموجود داخله عندما لا يكون الشرط متحققًا.
__name__ ثابت دائمًا. قيمته تعتمد على سياق تشغيل Module.
__main__ هي دالة. لا، هي String خاصة تستخدم كاسم للبيئة الأعلى.

متى لا تحتاج إلى Main Guard؟

لا تحتاجه إذا كان الملف يحتوي فقط على تعريفات تريد استيرادها وليس فيه كود تشغيل:

PI = 3.14159


def circle_area(radius):
    return (
        PI
        * radius
        * radius
    )

وجود Main Guard هنا لن يضيف فائدة إلا إذا أردت Demo أو نقطة تشغيل.

متى يصبح مهمًا جدًا؟

يصبح مفيدًا خصوصًا عندما يكون الملف يحتوي:

  • input() أو واجهة تفاعلية.
  • قراءة Arguments من سطر الأوامر.
  • بدء Server.
  • تشغيل Loop رئيسية.
  • قراءة أو كتابة ملفات عند بدء البرنامج.
  • إنشاء اتصالات خارجية.
  • Demo ترغب في تشغيله فقط عند تشغيل الملف مباشرة.

مثال مع قراءة ملف

from pathlib import Path


def load_text(path):
    return Path(path).read_text(
        encoding="utf-8"
    )


def main():
    text = load_text(
        "notes.txt"
    )

    print(text)


if __name__ == "__main__":
    main()

إذا استوردت load_text في مكان آخر، لن يقرأ البرنامج notes.txt تلقائيًا لمجرد الاستيراد.

مثال مع API أو شبكة

القاعدة نفسها: لا تجعل طلبات الشبكة تحدث عند Import بلا سبب. ضع نقطة التشغيل في Function واستدعها عند الحاجة.

مثلًا من حيث التنظيم:

def fetch_data():
    # network request
    pass


def main():
    data = fetch_data()

    print(data)


if __name__ == "__main__":
    main()

هل يمكن استدعاء main() من ملف آخر؟

نعم إذا كانت معرفة على مستوى Module:

import app


app.main()

Main Guard لا يجعل main() خاصة أو مخفية. هو فقط يتحكم في الاستدعاء التلقائي عند تشغيل الملف مباشرة.

هل يمكن أن أستخدم اسمًا آخر بدل main؟

نعم:

def run():
    print("Running")


if __name__ == "__main__":
    run()

لكن main() تجعل القصد واضحًا لأي مبرمج يقرأ الملف.

تمرين عملي

أنشئ ملفًا باسم temperature.py يحتوي Function:

def celsius_to_fahrenheit(c):
    return (
        c * 9 / 5
    ) + 32

ثم أنشئ main() تسأل المستخدم عن درجة الحرارة وتطبع النتيجة، واجعلها تعمل فقط عند تشغيل الملف مباشرة.

حل مقترح

def celsius_to_fahrenheit(c):
    return (
        c * 9 / 5
    ) + 32


def main():
    celsius = float(
        input(
            "Enter Celsius: "
        )
    )

    fahrenheit = (
        celsius_to_fahrenheit(
            celsius
        )
    )

    print(
        "Fahrenheit:",
        fahrenheit
    )


if __name__ == "__main__":
    main()

اختبر الآن الاستيراد

أنشئ ملفًا آخر:

from temperature import (
    celsius_to_fahrenheit
)


print(
    celsius_to_fahrenheit(
        30
    )
)

يجب أن تعمل Function مباشرة بدون أن يسألك Module عن درجة حرارة عبر input().

قائمة فحص لفهم __name__ و__main__

  • هل تعرف أن __name__ توفره بايثون داخل Module؟
  • هل تعرف أن قيمته تصبح "__main__" عند تشغيل الملف كبيئة أعلى؟
  • هل تعرف أنها تصبح اسم Module عند Import؟
  • هل تعرف لماذا يمنع Main Guard كود التشغيل من العمل أثناء Import؟
  • هل تعرف أن main() ليست إلزامية في بايثون؟
  • هل تستطيع فصل Functions القابلة لإعادة الاستخدام عن كود التشغيل؟
  • هل تعرف أن main.py اسم عادي بينما __main__.py له معنى خاص في Packages؟

روابط داخلية مفيدة من بايثون العرب

مصادر رسمية للتوسع

الخلاصة

if __name__ == "__main__": ليست تعويذة يجب نسخها في نهاية كل ملف بايثون. هي طريقة واضحة لمعرفة هل Module يعمل كنقطة تشغيل رئيسية أم تم استيراده داخل برنامج آخر.

عندما تشغّل ملفًا مباشرة، تكون قيمة __name__ فيه "__main__"، ولذلك يعمل الكود داخل Main Guard. وعندما تستورد الملف، تصبح __name__ اسم Module، فلا يعمل كود التشغيل الموجود داخل الشرط.

أفضل استخدام عملي هو تعريف Functions وClasses القابلة لإعادة الاستخدام في المستوى المناسب، ووضع خطوات تشغيل البرنامج داخل main()، ثم استدعائها بهذا الشكل:

if __name__ == "__main__":
    main()

بهذا تحصل على ملف يمكن تشغيله مباشرة، ويمكن أيضًا استيراد أجزائه بدون آثار جانبية غير مرغوبة.

{alertSuccess} القاعدة المهمة: ضع المنطق القابل لإعادة الاستخدام داخل Functions وClasses، وضع نقطة تشغيل البرنامج داخل main()، واستخدم Main Guard عندما تريد أن تعمل نقطة التشغيل فقط عند تشغيل الملف مباشرة.

أسئلة شائعة

ما معنى if __name__ == "__main__" في بايثون؟

يعني تنفيذ الكود الموجود داخل الشرط فقط عندما يعمل Module كبيئة التشغيل الأعلى، وليس عندما يتم استيراده كـModule داخل ملف آخر.

ما هي قيمة __name__ عند تشغيل ملف بايثون مباشرة؟

تكون "__main__".

ما هي قيمة __name__ عند import؟

تكون عادةً اسم Module، وقد يتضمن الاسم مسار Package إذا كان Module جزءًا من Package.

لماذا نستخدم if __name__ == "__main__"؟

لمنع كود التشغيل الرئيسي من العمل تلقائيًا أثناء Import، مع إبقاء Functions وClasses قابلة لإعادة الاستخدام.

هل main() إلزامية في بايثون؟

لا. main() مجرد اتفاقية شائعة لتنظيم نقطة تشغيل البرنامج.

هل يجب أن يكون اسم الملف main.py؟

لا. يمكن أن يكون اسم الملف app.py أو run.py أو أي اسم مناسب.

ما الفرق بين main.py و__main__.py؟

main.py اسم ملف عادي، أما __main__.py فهو اسم خاص يمكن استخدامه كنقطة تشغيل Package عند تشغيلها باستخدام python -m package_name.

ما معنى Main Guard؟

هو الاسم الشائع للشرط if __name__ == "__main__": الذي يحمي كود نقطة التشغيل من العمل عند Import.

هل import يشغل الكود الموجود في الملف؟

ينفذ Top-level Code عند تحميل Module، لذلك يجب تجنب وضع عمليات تشغيل غير مرغوبة في المستوى الأعلى إذا كان الملف سيُستورد.

هل تعريف Function ينفذ محتواها أثناء Import؟

لا. يتم إنشاء Function عند تنفيذ تعريفها، لكن جسمها لا يعمل حتى يتم استدعاؤها.

هل يمكن استيراد Function من ملف يستخدم Main Guard؟

نعم، إذا كانت Function معرفة خارج Main Guard.

هل يمكن استدعاء main() من ملف آخر؟

نعم، إذا كانت main معرفة كFunction عادية في Module، يمكنك استيراد Module واستدعاء module.main() صراحة.

هل if __name__ == "__main__" تحسن سرعة البرنامج؟

هدفها الأساسي تنظيم التنفيذ وليس تحسين الأداء.

هل هي آلية أمان؟

لا. لا تمنع الوصول إلى الكود أو تشغيله؛ هي فقط تتحكم فيما ينفذ تلقائيًا حسب سياق Module.

هل تعمل مع python -m؟

نعم. Module الذي يعمل كنقطة تشغيل أعلى باستخدام python -m يكون اسمه في ذلك السياق __main__.

متى لا أحتاج Main Guard؟

إذا كان الملف مجرد Module يحتوي Functions وClasses ولا يوجد فيه كود تشغيل مباشر أو Demo يحتاج الحماية، فقد لا تحتاجه.

ما أفضل شكل شائع للبرنامج؟

تعريف Imports ثم Constants ثم Functions وClasses، وبعدها main()، وفي النهاية if __name__ == "__main__": main().

إرسال تعليق

أحدث أقدم