سؤال

ماذا يكون ال if __name__ == "__main__": يفعل؟

# Threading example
import time, thread

def myfunction(string, sleeptime, lock, *args):
    while True:
        lock.acquire()
        time.sleep(sleeptime)
        lock.release()
        time.sleep(sleeptime)

if __name__ == "__main__":
    lock = thread.allocate_lock()
    thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
    thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))
هل كانت مفيدة؟

المحلول

عندما يقرأ مترجم بايثون الملف المصدر، فإنه يفعل شيئين:

  • يقوم بتعيين بعض المتغيرات الخاصة مثل __name__, ، وثم

  • يقوم بتنفيذ كافة التعليمات البرمجية الموجودة في الملف.

دعونا نرى كيف يعمل هذا ومدى ارتباطه بسؤالك حول __name__ الشيكات التي نراها دائمًا في نصوص بايثون.

نموذج التعليمات البرمجية

دعونا نستخدم نموذج تعليمات برمجية مختلف قليلاً لاستكشاف كيفية عمل عمليات الاستيراد والبرامج النصية.لنفترض أن ما يلي موجود في ملف يسمى foo.py.

# Suppose this is foo.py.

print("before import")
import math

print("before functionA")
def functionA():
    print("Function A")

print("before functionB")
def functionB():
    print("Function B {}".format(math.sqrt(100)))

print("before __name__ guard")
if __name__ == '__main__':
    functionA()
    functionB()
print("after __name__ guard")

المتغيرات الخاصة

عندما يقرأ مُترجم لغة بايثون ملفًا مصدريًا، فإنه يقوم أولاً بتعريف بعض المتغيرات الخاصة.في هذه الحالة، نحن نهتم __name__ عامل.

عندما تكون الوحدة الخاصة بك هي البرنامج الرئيسي

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

python foo.py

سيقوم المترجم بتعيين السلسلة المشفرة "__main__" إلى __name__ متغير، أي

# It's as if the interpreter inserts this at the top
# of your module when run as the main program.
__name__ = "__main__" 

عندما يتم استيراد الوحدة الخاصة بك بواسطة وحدة أخرى

من ناحية أخرى، لنفترض أن بعض الوحدات الأخرى هي البرنامج الرئيسي وتقوم باستيراد الوحدة الخاصة بك.هذا يعني أن هناك عبارة مثل هذه في البرنامج الرئيسي، أو في بعض الوحدات الأخرى التي يستوردها البرنامج الرئيسي:

# Suppose this is in some other main program.
import foo

في هذه الحالة، سوف ينظر المترجم إلى اسم ملف الوحدة الخاصة بك، foo.py, ، تجريد .py, ، وقم بتعيين هذه السلسلة إلى الوحدة النمطية الخاصة بك __name__ متغير، أي

# It's as if the interpreter inserts this at the top
# of your module when it's imported from another module.
__name__ = "foo"

تنفيذ رمز الوحدة

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

دائماً

  1. يقوم بطباعة السلسلة "before import" (بدون اقتباسات).

  2. يقوم بتحميل math الوحدة النمطية وتخصيصها لمتغير يسمى math.وهذا يعادل استبدال import math مع ما يلي (لاحظ ذلك __import__ هي وظيفة منخفضة المستوى في بايثون تأخذ سلسلة وتؤدي إلى الاستيراد الفعلي):

# Find and load a module given its string name, "math",
# then assign it to a local variable called math.
math = __import__("math")
  1. يقوم بطباعة السلسلة "before functionA".

  2. يقوم بتنفيذ def block، وإنشاء كائن دالة، ثم تعيين كائن الوظيفة هذا إلى متغير يسمى functionA.

  3. يقوم بطباعة السلسلة "before functionB".

  4. وينفذ الثاني def block، وإنشاء كائن دالة آخر، ثم إسناده إلى متغير يسمى functionB.

  5. يقوم بطباعة السلسلة "before __name__ guard".

فقط عندما تكون الوحدة الخاصة بك هي البرنامج الرئيسي

  1. إذا كانت الوحدة الخاصة بك هي البرنامج الرئيسي، فسوف ترى ذلك __name__ تم تعيينه بالفعل على "__main__" ويستدعي الوظيفتين، ويطبع السلاسل "Function A" و "Function B 10.0".

فقط عندما يتم استيراد الوحدة الخاصة بك بواسطة وحدة أخرى

  1. (بدلاً من) إذا لم تكن الوحدة الخاصة بك هي البرنامج الرئيسي ولكن تم استيرادها بواسطة برنامج آخر، إذن __name__ سوف يكون "foo", ، لا "__main__", ، وسوف يتخطى جسم if إفادة.

دائماً

  1. سيتم طباعة السلسلة "after __name__ guard" في كلتا الحالتين.

ملخص

وخلاصة هذا ما سيتم طباعته في الحالتين:

# What gets printed if foo is the main program
before import
before functionA
before functionB
before __name__ guard
Function A
Function B 10.0
after __name__ guard
# What gets printed if foo is imported as a regular module
before import
before functionA
before functionB
before __name__ guard
after __name__ guard

لماذا يعمل بهذه الطريقة؟

قد تتساءل بطبيعة الحال لماذا يريد أي شخص هذا.حسنا، في بعض الأحيان تريد أن تكتب .py ملف يمكن استخدامه بواسطة برامج و/أو وحدات أخرى كوحدة نمطية، ويمكن أيضًا تشغيله باعتباره البرنامج الرئيسي نفسه.أمثلة:

  • الوحدة الخاصة بك عبارة عن مكتبة، ولكنك تريد أن يكون لديك وضع برنامج نصي حيث يتم تشغيل بعض اختبارات الوحدة أو العرض التوضيحي.

  • يتم استخدام الوحدة الخاصة بك فقط كبرنامج رئيسي، ولكنها تحتوي على بعض اختبارات الوحدة، ويعمل إطار الاختبار عن طريق الاستيراد .py ملفات مثل البرنامج النصي الخاص بك وتشغيل وظائف الاختبار الخاصة.لا تريده أن يحاول تشغيل البرنامج النصي لمجرد أنه يستورد الوحدة.

  • يتم استخدام الوحدة الخاصة بك في الغالب كبرنامج رئيسي، ولكنها توفر أيضًا واجهة برمجة تطبيقات سهلة الاستخدام للمبرمجين للمستخدمين المتقدمين.

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

غذاء للفكر

  • سؤال:هل يمكنني الحصول على عدة __name__ فحص الكتل؟إجابة:من الغريب أن تفعل ذلك، لكن اللغة لن تمنعك.

  • لنفترض أن ما يلي موجود foo2.py.ماذا يحدث إذا قلت python foo2.py على سطر الأوامر؟لماذا؟

# Suppose this is foo2.py.

def functionA():
    print("a1")
    from foo2 import functionB
    print("a2")
    functionB()
    print("a3")

def functionB():
    print("b")

print("t1")
if __name__ == "__main__":
    print("m1")
    functionA()
    print("m2")
print("t2")
  • الآن اكتشف ما سيحدث إذا قمت بإزالة الملف __name__ تحقق في foo3.py:
# Suppose this is foo3.py.

def functionA():
    print("a1")
    from foo3 import functionB
    print("a2")
    functionB()
    print("a3")

def functionB():
    print("b")

print("t1")
print("m1")
functionA()
print("m2")
print("t2")
  • ماذا سيفعل هذا عند استخدامه كبرنامج نصي؟عند استيرادها كوحدة نمطية؟
# Suppose this is in foo4.py
__name__ = "__main__"

def bar():
    print("bar")

print("before __name__ guard")
if __name__ == "__main__":
    bar()
print("after __name__ guard")

نصائح أخرى

عند تشغيل البرنامج النصي الخاص بك عن طريق تمرير بأنها الأمر إلى مترجم Python،

python myscript.py

وكافة التعليمات البرمجية التي هي في مستوى المسافة البادئة 0 يعدم. الوظائف والفئات التي يتم تعريفها هي، أيضا، تعريف، ولكن يحصل تشغيل أي من التعليمات البرمجية الخاصة بهم. وخلافا لغات أخرى، وليس هناك وظيفة main() أن يحصل على تشغيل تلقائيا - وظيفة main() هي ضمنا كافة التعليمات البرمجية على أعلى مستوى

.

في هذه الحالة، رمز المستوى الأعلى هو كتلة if. __name__ هو متغير المدمج الذي يقيم إلى اسم الوحدة النمطية الحالية. ومع ذلك، إذا كان يتم تشغيل وحدة مباشرة (كما هو الحال في myscript.py أعلاه)، ثم __name__ بدلا تم تعيينها إلى "__main__" السلسلة. وهكذا، يمكنك اختبار ما إذا كان يتم تشغيل البرنامج النصي الخاص بك مباشرة أو التي يتم استيرادها من قبل أي شيء آخر عن طريق اختبار

if __name__ == "__main__":
    ...

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

# file one.py
def func():
    print("func() in one.py")

print("top-level in one.py")

if __name__ == "__main__":
    print("one.py is being run directly")
else:
    print("one.py is being imported into another module")
# file two.py
import one

print("top-level in two.py")
one.func()

if __name__ == "__main__":
    print("two.py is being run directly")
else:
    print("two.py is being imported into another module")

والآن، إذا كنت استدعاء مترجم ك

python one.py

وسوف يكون الإخراج

top-level in one.py
one.py is being run directly

إذا قمت بتشغيل two.py بدلا من ذلك:

python two.py

ويمكنك الحصول على

top-level in one.py
one.py is being imported into another module
top-level in two.py
func() in one.py
two.py is being run directly

وهكذا، عندما يحصل على تحميل وحدة one، __name__ لها يساوي "one" بدلا من "__main__".

وأبسط تفسير لمتغير __name__ (إيمهو) هو ما يلي:

وإنشاء الملفات التالية.

# a.py
import b

و

# b.py
print "Hello World from %s!" % __name__

if __name__ == '__main__':
    print "Hello World again from %s!" % __name__

والجري منهم سوف تحصل على هذا الناتج:

$ python a.py
Hello World from b!

وكما ترون، عندما يتم استيرادها وحدة نمطية بيثون يحدد globals()['__name__'] في هذه الوحدة إلى اسم الوحدة النمطية. أيضا، عند الاستيراد كافة التعليمات البرمجية في وحدة يتم تشغيل. كما يقيم بيان if إلى False هذا الجزء لم ينفذ.

$ python b.py
Hello World from __main__!
Hello World again from __main__!

وكما ترون، عندما يتم تنفيذ ملف، بيثون يحدد globals()['__name__'] في هذا الملف إلى "__main__". هذه المرة، وبيان if يقيم لTrue ويتم تشغيل.

ماذا يكون ال if __name__ == "__main__": يفعل؟

لتوضيح الأساسيات:

  • المتغير العالمي __name__, ، في الوحدة التي تمثل نقطة الدخول إلى برنامجك، هي '__main__'.بخلاف ذلك، فهو الاسم الذي تستورد الوحدة به.

  • لذلك، رمز تحت if سيتم تشغيل الكتلة فقط إذا كانت الوحدة هي نقطة الدخول إلى برنامجك.

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


لماذا نحتاج هذا؟

تطوير واختبار التعليمات البرمجية الخاصة بك

لنفترض أنك تكتب نصًا برمجيًا بلغة Python مصممًا لاستخدامه كوحدة نمطية:

def do_important():
    """This function does something very important"""

أنت استطاع اختبر الوحدة عن طريق إضافة استدعاء الوظيفة إلى الأسفل:

do_important()

وتشغيله (في موجه الأوامر) بشيء مثل:

~$ python important.py

المشكلة

ومع ذلك، إذا كنت تريد استيراد الوحدة إلى برنامج نصي آخر:

import important

عند الاستيراد، do_important سيتم استدعاء الوظيفة، لذلك من المحتمل أن تعلق على استدعاء وظيفتك، do_important(), ، في الأسفل.

# do_important() # I must remember to uncomment to execute this!

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

طريقة أفضل

ال __name__ يشير المتغير إلى مساحة الاسم أينما كان مترجم بايثون موجودًا في الوقت الحالي.

داخل الوحدة النمطية المستوردة، يكون اسم تلك الوحدة.

ولكن داخل الوحدة الأساسية (أو جلسة بايثون التفاعلية، على سبيل المثال:قراءة المترجم أو تقييمه أو حلقة الطباعة أو REPL) التي تقوم بتشغيل كل شيء منها "__main__".

لذلك إذا قمت بالتحقق قبل التنفيذ:

if __name__ == "__main__":
    do_important()

مع ما سبق، لن يتم تنفيذ التعليمات البرمجية الخاصة بك إلا عند تشغيلها كوحدة أساسية (أو استدعائها عمدًا من برنامج نصي آخر).

طريقة أفضل

هناك طريقة بايثونية لتحسين هذا الأمر.

ماذا لو أردنا تشغيل عملية الأعمال هذه من خارج الوحدة؟

إذا وضعنا الكود الذي نريد أن نتدرب عليه أثناء تطويرنا واختبارنا لوظيفة كهذه ثم نقوم بالتحقق منها '__main__' مباشرة بعد:

def main():
    """business logic for when running this module as the primary one!"""
    setup()
    foo = do_important()
    bar = do_even_more_important(foo)
    for baz in bar:
        do_super_important(baz)
    teardown()

# Here's our payoff idiom!
if __name__ == '__main__':
    main()

لدينا الآن وظيفة نهائية لنهاية الوحدة الخاصة بنا والتي سيتم تشغيلها إذا قمنا بتشغيل الوحدة باعتبارها الوحدة الأساسية.

سيسمح باستيراد الوحدة ووظائفها وفئاتها إلى نصوص برمجية أخرى دون تشغيل الملف main وظيفة، وسيسمح أيضًا باستدعاء الوحدة النمطية (ووظائفها وفئاتها) عند تشغيلها من جهاز مختلف '__main__' الوحدة النمطية، أي

import important
important.main()

يمكن أيضًا العثور على هذا المصطلح في وثائق Python في شرح لـ __main__ وحدة. ينص هذا النص على:

تمثل هذه الوحدة النطاق (المجهول) الذي ينفذ فيه البرنامج الرئيسي للمترجم المترجم - أوامر يقرأ إما من الإدخال القياسي ، أو من ملف البرنامج النصي ، أو من مطالبة تفاعلية.هذه هي البيئة التي يتسبب فيها ستانزا "البرنامج النصي الشرطي" في تشغيل البرنامج النصي:

if __name__ == '__main__':
    main()

وif __name__ == "__main__" هو الجزء الذي يعمل عند تشغيل البرنامج النصي من (مثلا) في سطر الأوامر باستخدام أمر مثل python myscript.py.

ماذا فعلت if __name__ == "__main__": يفعل؟

__name__ هو متغير عالمي (في لغة Python، كلمة global تعني في الواقع على مستوى الوحدة) الموجود في كافة مساحات الأسماء.عادةً ما يكون اسم الوحدة النمطية (بامتداد str يكتب).

ومع ذلك، باعتبارها الحالة الخاصة الوحيدة، في أي عملية بايثون تقوم بتشغيلها، كما هو الحال في mycode.py:

python mycode.py

يتم تعيين قيمة مساحة الاسم العالمية المجهولة '__main__' لها __name__.

وهكذا، بما في ذلك الخطوط النهائية

if __name__ == '__main__':
    main()
  • في نهاية البرنامج النصي mycode.py الخاص بك،
  • عندما تكون وحدة نقطة الإدخال الأساسية التي يتم تشغيلها بواسطة عملية بايثون،

سيؤدي إلى تعريف البرنامج النصي الخاص بك بشكل فريد main وظيفة للتشغيل.

فائدة أخرى لاستخدام هذا البناء:يمكنك أيضًا استيراد التعليمات البرمجية الخاصة بك كوحدة نمطية في برنامج نصي آخر ثم تشغيل الوظيفة الرئيسية إذا قرر برنامجك ذلك:

import mycode
# ... any amount of other code
mycode.main()

هناك الكثير من الأفكار المختلفة هنا حول آليات الكود المعني، "كيف"، ولكن بالنسبة لي لم يكن أي منها منطقيًا حتى فهمت "لماذا".يجب أن يكون هذا مفيدًا بشكل خاص للمبرمجين الجدد.

خذ الملف "ab.py":

def a():
    print('A function in ab file');
a()

والملف الثاني "xy.py":

import ab
def main():
    print('main function: this is where the action is')
def x():
    print ('peripheral task: might be useful in other projects')
x()
if __name__ == "__main__":
    main()

ما الذي يفعله هذا الرمز فعليًا؟

عند التنفيذ xy.py, ، أنت import ab.يقوم بيان الاستيراد بتشغيل الوحدة فورًا عند الاستيراد، لذلك abيتم تنفيذ عمليات قبل بقية xy'س.بمجرد الانتهاء من ab, ، ويستمر مع xy.

يقوم المترجم بتتبع البرامج النصية التي يتم تشغيلها معها __name__.عندما تقوم بتشغيل برنامج نصي - بغض النظر عن الاسم الذي قمت بتسميته - يقوم المترجم باستدعائه "__main__", مما يجعله البرنامج النصي الرئيسي أو "الرئيسي" الذي يتم الرجوع إليه بعد تشغيل برنامج نصي خارجي.

أي برنامج نصي آخر يتم استدعاؤه من هذا "__main__" تم تعيين اسم الملف الخاص بالبرنامج النصي على أنه ملف __name__ (على سبيل المثال، __name__ == "ab.py").وبالتالي الخط if __name__ == "__main__": هو اختبار للمترجم لتحديد ما إذا كان يقوم بتفسير/تحليل البرنامج النصي "المنزلي" الذي تم تنفيذه في البداية، أو ما إذا كان ينظر مؤقتًا إلى برنامج نصي (خارجي) آخر.وهذا يمنح المبرمج المرونة لجعل البرنامج النصي يتصرف بشكل مختلف إذا تم تنفيذه مباشرة مقابل تنفيذه مباشرة.دعا خارجيا.

دعونا ننتقل إلى الكود أعلاه لفهم ما يحدث، مع التركيز أولاً على الأسطر غير البادئة والترتيب الذي تظهر به في البرامج النصية.تذكر تلك الوظيفة - أو def - الكتل لا تفعل أي شيء من تلقاء نفسها حتى يتم استدعاؤها.ما قد يقوله المترجم إذا تمتم لنفسه:

  • افتح xy.py كملف "الصفحة الرئيسية"؛نسميها "__main__" في ال __name__ عامل.
  • قم باستيراد الملف وفتحه باستخدام ملف __name__ == "ab.py".
  • أوه، وظيفة.سوف اتذكر ذلك.
  • طيب، وظيفة a();لقد تعلمت ذلك للتو.الطباعة 'دالة في ملف ab'.
  • نهاية الملف؛ارجع الى "__main__"!
  • أوه، وظيفة.سوف اتذكر ذلك.
  • واحدة أخرى.
  • وظيفة x();طيب الطباعة"المهمة الطرفية:قد تكون مفيدة في مشاريع أخرى'.
  • ما هذا؟ان if إفادة.حسنًا، لقد تم استيفاء الشرط (المتغير __name__ تم ضبطه على "__main__")، لذلك سأدخل main() الوظيفة والطباعة "الوظيفة الأساسية:هذا هو المكان الذي يوجد فيه العمل'.

السطران السفليان يعنيان:"إذا كان هذا هو "__main__" أو البرنامج النصي "المنزلي"، قم بتنفيذ الوظيفة المسماة main()".لهذا السبب سترى أ def main(): الكتلة العلوية، والتي تحتوي على التدفق الرئيسي لوظيفة البرنامج النصي.

لماذا تنفيذ هذا؟

هل تتذكر ما قلته سابقًا عن بيانات الاستيراد؟عندما تقوم باستيراد وحدة نمطية، فإنها لا تتعرف عليها وتنتظر المزيد من التعليمات فحسب، بل تقوم في الواقع بتشغيل جميع العمليات القابلة للتنفيذ الموجودة داخل البرنامج النصي.لذا، ضع جوهر النص الخاص بك في main() تقوم الوظيفة بعزله بشكل فعال، مما يجعله في عزلة بحيث لا يتم تشغيله على الفور عند استيراده بواسطة برنامج نصي آخر.

مرة أخرى، ستكون هناك استثناءات، ولكن الممارسة الشائعة هي ذلك main() لا يتم الاتصال به عادةً خارجيًا.لذلك ربما تتساءل عن شيء آخر:إذا لم نتصل main(), لماذا نسمي البرنامج النصي على الإطلاق؟يرجع السبب في ذلك إلى أن العديد من الأشخاص يقومون ببناء البرامج النصية الخاصة بهم بوظائف مستقلة تم تصميمها ليتم تشغيلها بشكل مستقل عن بقية التعليمات البرمجية الموجودة في الملف.ثم يتم استدعاؤهم لاحقًا في مكان آخر في نص البرنامج النصي.الذي يقودني إلى هذا:

لكن الكود يعمل بدونه

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

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

عند تقسيم الوظائف المستقلة، ستكتسب القدرة على إعادة استخدام عملك السابق عن طريق استدعائها في برنامج نصي آخر.على سبيل المثال، قد يقوم "example.py" باستيراد "xy.py" والاتصال به x(), ، مع الاستفادة من الدالة "x" من "xy.py".(ربما يتم تكبير الكلمة الثالثة من سلسلة نصية معينة؛إنشاء مصفوفة NumPy من قائمة الأرقام وتربيعها؛أو إزالة سطح ثلاثي الأبعاد.الاحتمالات لا حدود لها.)

( جانبا، هذا السؤال يحتوي على إجابة من @kindall والتي ساعدتني أخيرًا على الفهم - السبب، وليس الكيفية.لسوء الحظ تم وضع علامة عليها كنسخة مكررة من هذا, وهو ما أعتقد أنه خطأ.)

وعندما تكون هناك بعض البيانات في وحدة لدينا (M.py) نحن نريد ليتم تنفيذها عندما سوف تكون قيد التشغيل الرئيسي باسم (يتم استيرادها)، ونحن يمكن أن تضع تلك التصريحات (اختبار الحالات، البيانات المطبوعة) في إطار هذه الكتلة if.

ووبشكل افتراضي (عند وحدة تشغيل والرئيسية، يتم استيراد) يتم تعيين متغير __name__ إلى "__main__"، وعندما سوف استيراده المتغير __name__ سوف تحصل على قيمة مختلفة، وعلى الأرجح اسم وحدة ('M') . وهذا مفيد في تشغيل أنواع مختلفة من الوحدات معا، وفصل المدخلات والمخرجات البيانات الخاصة وأيضا إذا كان هناك أي-حالات الاختبار.

في القصير ، أو استخدام هذه "if __name__ == "main"" كتلة لمنع مدونة (معين) من تشغيل عندما يتم استيراد الوحدة.

ودعونا ننظر في الإجابة بطريقة أكثر تجريدا:

ونفترض أن لدينا هذا الرمز في x.py:

...
<Block A>
if __name__ == '__main__':
    <Block B>
...

ويتم تشغيل كتل ألف وباء عندما تقوم بتشغيل "x.py".

ولكن فقط منع A (وليس B) يتم تشغيله عندما تقوم بتشغيل وحدة أخرى، "y.py" على سبيل المثال، يتم استيراد التي XY وتشغيل رمز من هناك (مثل عندما وظيفة في "س. ويسمى الحمر "من y.py).

وببساطة، __name__ هو متغير المحددة لكل النصي الذي يحدد ما إذا كان يتم تشغيل البرنامج النصي وكذلك وحدة الرئيسية أو يتم تشغيله كما وحدة المستوردة.

وحتى لو كان لدينا اثنين من النصوص؛

#script1.py
print "Script 1's name: {}".format(__name__)

و

#script2.py
import script1
print "Script 2's name: {}".format(__name__)

والإخراج من تنفيذ script1 هو

Script 1's name: __main__

والإخراج من تنفيذ script2 هو:

Script1's name is script1
Script 2's name: __main__

وكما ترون، __name__ يقول لنا أي كود هي وحدة "الرئيسية". هذا شيء عظيم، لأنه يمكنك فقط كتابة التعليمات البرمجية وليس لديها ما يدعو للقلق حول القضايا الهيكلية مثل في C / C ++، حيث، إذا لم يكن ملف تنفيذ وظيفة "الرئيسية" ثم فإنه لا يمكن تجميعها وقابل للتنفيذ، وإذا فعلت ذلك، فإنه لا يمكن بعد ذلك أن تستخدم كمكتبة.

ونقول لكم كتابة السيناريو بيثون أن يفعل شيئا كبيرا وقمت بتطبيق حمولة السفينة من الوظائف التي هي مفيدة لأغراض أخرى. إذا كنت ترغب في استخدامها يمكنني استيراد فقط السيناريو الخاص بك واستخدامها دون تنفيذ البرنامج (بالنظر إلى أن تنفيذ التعليمات البرمجية فقط في سياق if __name__ == "__main__":). في حين أنه في C / C ++ وعملتم على جزء من هذه القطع في وحدة نمطية منفصلة ثم يتضمن الملف. صورة الوضع أدناه؛

والسهام وصلات الاستيراد. لثلاث وحدات يحاول كل لتتضمن رمز وحدات السابق هناك ستة ملفات (تسعة، عد ملفات التنفيذ) وخمسة الروابط. وهذا يجعل من الصعب تشمل تعليمات برمجية أخرى في مشروع C ما لم يتم ترجمة ذلك على وجه التحديد كمكتبة. الآن تصوير ذلك لبيثون:

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

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

if __name__ == '__main__':
    # Do something appropriate here, like calling a
    # main() function defined elsewhere in this module.
    main()
else:
    # Do nothing. This module has been imported by another
    # module that wants to make use of the functions,
    # classes and other useful bits it has defined.

والنظر فيما يلي:

if __name__ == "__main__":
    main()

وويتحقق إذا كانت السمة __name__ من السيناريو بيثون هي "__main__". وبعبارة أخرى، إذا تم تنفيذ البرنامج في حد ذاته، سيتم __main__ السمة، لذلك سيتم تنفيذ البرنامج (في هذه الحالة وظيفة main()).

ولكن، إذا تم استخدام بيثون السيناريو الخاص بك عن طريق وحدة نمطية، وسيتم تنفيذ أي رمز من خارج بيان if، بحيث يتم استخدام if \__name__ == "\__main__" فقط لمعرفة ما اذا كان يستخدم برنامج وحدة نمطية أم لا، وبالتالي يقرر ما إذا كان تشغيل التعليمات البرمجية.

Before explaining anything about if __name__ == '__main__' it is important to understand what __name__ is and what it does.

What is __name__?

__name__ is a DunderAlias - can be thought of as a global variable (accessible from modules) and works in a similar way to global.

It is a string (global as mentioned above) as indicated by type(__name__) (yielding <class 'str'>), and is an inbuilt standard for both Python 3 and Python 2 versions.

Where:

It can not only be used in scripts but can also be found in both the interpreter and modules/packages.

Interpreter:

>>> print(__name__)
__main__
>>>

Script:

test_file.py:

print(__name__)

Resulting in __main__

Module or package:

somefile.py:

def somefunction():
    print(__name__)

test_file.py:

import somefile
somefile.somefunction()

Resulting in somefile

Notice that when used in a package or module, __name__ takes the name of the file. The path of the actual module or package path is not given, but has its own DunderAlias __file__, that allows for this.

You should see that, where __name__, where it is the main file (or program) will always return __main__, and if it is a module/package, or anything that is running off some other Python script, will return the name of the file where it has originated from.

Practice:

Being a variable means that it's value can be overwritten ("can" does not mean "should"), overwriting the value of __name__ will result in a lack of readability. So do not do it, for any reason. If you need a variable define a new variable.

It is always assumed that the value of __name__ to be __main__ or the name of the file. Once again changing this default value will cause more confusion that it will do good, causing problems further down the line.

example:

>>> __name__ = 'Horrify' # Change default from __main__
>>> if __name__ == 'Horrify': print(__name__)
...
>>> else: print('Not Horrify')
...
Horrify
>>>

It is considered good practice in general to include the if __name__ == '__main__' in scripts.

Now to answer if __name__ == '__main__':

Now we know the behaviour of __name__ things become clearer:

An if is a flow control statement that contains the block of code will execute if the value given is true. We have seen that __name__ can take either __main__ or the file name it has been imported from.

This means that if __name__ is equal to __main__ then the file must be the main file and must actually be running (or it is the interpreter), not a module or package imported into the script.

If indeed __name__ does take the value of __main__ then whatever is in that block of code will execute.

This tells us that if the file running is the main file (or you are running from the interpreter directly) then that condition must execute. If it is a package then it should not, and the value will not be __main__.

Modules:

__name__ can also be used in modules to define the name of a module

Variants:

It is also possible to do other, less common but useful things with __name__, some I will show here:

Executing only if the file is a module or package:

if __name__ != '__main__':
    # Do some useful things 

Running one condition if the file is the main one and another if it is not:

if __name__ == '__main__':
    # Execute something
else:
    # Do some useful things

You can also use it to provide runnable help functions/utilities on packages and modules without the elaborate use of libraries.

It also allows modules to be run from the command line as main scripts, which can be also very useful.

I think it's best to break the answer in depth and in simple words:

__name__: Every module in Python has a special attribute called __name__. It is a built-in variable that returns the name of the module.

__main__: Like other programming languages, Python too has an execution entry point, i.e., main. '__main__' is the name of the scope in which top-level code executes. Basically you have two ways of using a Python module: Run it directly as a script, or import it. When a module is run as a script, its __name__ is set to __main__.

Thus, the value of the __name__ attribute is set to __main__ when the module is run as the main program. Otherwise the value of __name__ is set to contain the name of the module.

It is a special for when a Python file is called from the command line. This is typically used to call a "main()" function or execute other appropriate startup code, like commandline arguments handling for instance.

It could be written in several ways. Another is:

def some_function_for_instance_main():
    dosomething()


__name__ == '__main__' and some_function_for_instance_main()

I am not saying you should use this in production code, but it serves to illustrate that there is nothing "magical" about if __name__ == '__main__'. It is a good convention for invoking a main function in Python files.

There are a number of variables that the system (Python interpreter) provides for source files (modules). You can get their values anytime you want, so, let us focus on the __name__ variable/attribute:

When Python loads a source code file, it executes all of the code found in it. (Note that it doesn't call all of the methods and functions defined in the file, but it does define them.)

Before the interpreter executes the source code file though, it defines a few special variables for that file; __name__ is one of those special variables that Python automatically defines for each source code file.

If Python is loading this source code file as the main program (i.e. the file you run), then it sets the special __name__ variable for this file to have a value "__main__".

If this is being imported from another module, __name__ will be set to that module's name.

So, in your example in part:

if __name__ == "__main__":
   lock = thread.allocate_lock()
   thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
   thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))

means that the code block:

lock = thread.allocate_lock()
thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))

will be executed only when you run the module directly; the code block will not execute if another module is calling/importing it because the value of __name__ will not equal to "main" in that particular instance.

Hope this helps out.

if __name__ == "__main__": is basically the top-level script environment, and it specifies the interpreter that ('I have the highest priority to be executed first').

'__main__' is the name of the scope in which top-level code executes. A module’s __name__ is set equal to '__main__' when read from standard input, a script, or from an interactive prompt.

if __name__ == "__main__":
    # Execute only if run as a script
    main()

The reason for

if __name__ == "__main__":
    main()

is primarily to avoid the import lock problems that would arise from having code directly imported. You want main() to run if your file was directly invoked (that's the __name__ == "__main__" case), but if your code was imported then the importer has to enter your code from the true main module to avoid import lock problems.

A side-effect is that you automatically sign on to a methodology that supports multiple entry points. You can run your program using main() as the entry point, but you don't have to. While setup.py expects main(), other tools use alternate entry points. For example, to run your file as a gunicorn process, you define an app() function instead of a main(). Just as with setup.py, gunicorn imports your code so you don't want it do do anything while it's being imported (because of the import lock issue).

I've been reading so much throughout the answers on this page. I would say, if you know the thing, for sure you will understand those answers, otherwise, you are still confused.

To be short, you need to know several points:

  1. import a action actually runs all that can be ran in "a"

  2. Because of point 1, you may not want everything to be run in "a" when importing it

  3. To solve the problem in point 2, python allows you to put a condition check

  4. __name__ is an implicit variable in all .py modules; when a.py is imported, the value of __name__ of a.py module is set to its file name "a"; when a.py is run directly using "python a.py", which means a.py is the entry point, then the value of __name__ of a.py module is set to a string __main__

  5. Based on the mechanism how python sets the variable __name__ for each module, do you know how to achieve point 3? The answer is fairly easy, right? Put a if condition: if __name__ == "__main__": ...; you can even put if __name__ == "a" depending on your functional need

The important thing that python is special at is point 4! The rest is just basic logic.

Consider:

print __name__

The output for the above is __main__.

if __name__ == "__main__":
  print "direct method"

The above statement is true and prints "direct method". Suppose if they imported this class in another class it doesn't print "direct method" because, while importing, it will set __name__ equal to "first model name".

You can make the file usable as a script as well as an importable module.

fibo.py (a module named fibo)

# Other modules can IMPORT this MODULE to use the function fib
def fib(n):    # write Fibonacci series up to n
    a, b = 0, 1
    while b < n:
        print(b, end=' ')
        a, b = b, a+b
    print()

# This allows the file to be used as a SCRIPT
if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

Reference: https://docs.python.org/3.5/tutorial/modules.html

This answer is for Java programmers learning Python. Every Java file typically contains one public class. You can use that class in two ways:

  1. Call the class from other files. You just have to import it in the calling program.

  2. Run the class stand alone, for testing purposes.

For the latter case, the class should contain a public static void main() method. In Python this purpose is served by the globally defined label '__main__'.

If this .py file are imported by other .py files, the code under "the if statement" will not be executed.

If this .py are run by python this_py.py under shell, or double clicked in Windows. the code under "the if statement" will be executed.

It is usually written for testing.

Create a file, a.py:

print(__name__) # It will print out __main__

__name__ is always equal to __main__ whenever that file is run directly showing that this is the main file.

Create another file, b.py, in the same directory:

import a  # Prints a

Run it. It will print a, i.e., the name of the file which is imported.

So, to show two different behavior of the same file, this is a commonly used trick:

# Code to be run when imported into another python file

if __name__ == '__main__':
    # Code to be run only when run directly

if name == 'main':

We see if __name__ == '__main__': quite often.

It checks if a module is being imported or not.

In other words, the code within the if block will be executed only when the code runs directly. Here directly means not imported.

Let's see what it does using a simple code that prints the name of the module:

# test.py
def test():
   print('test module name=%s' %(__name__))

if __name__ == '__main__':
   print('call test()')
   test()

If we run the code directly via python test.py, the module name is __main__:

call test()
test module name=__main__

All the answers have pretty much explained the functionality. But I will provide one example of its usage which might help clearing out the concept further.

Assume that you have two Python files, a.py and b.py. Now, a.py imports b.py. We run the a.py file, where the "import b.py" code is executed first. Before the rest of the a.py code runs, the code in the file b.py must run completely.

In the b.py code there is some code that is exclusive to that file b.py and we don't want any other file (other than b.py file), that has imported the b.py file, to run it.

So that is what this line of code checks. If it is the main file (i.e., b.py) running the code, which in this case it is not (a.py is the main file running), then only the code gets executed.

Simply it is the entry point to run the file like the main function in the C programming language.

Every module in python has a attribute which is called as name . The value of name attribute is 'main' when module run directly. Otherwise the value of name is the name of the module.

Small example to explain in short.

#Script test.py

apple = 42

def hello_world():
    print("I am inside hello_world")

if __name__ == "__main__":
    print("Value of __name__ is: ", __name__)
    print("Going to call hello_world")
    hello_world()

We can execute this directly as

python test.py  

Output

Value of __name__ is: __main__
Going to call hello_world
I am inside hello_world

Now suppose we call above script from other script

#script external_calling.py

import test
print(test.apple)
test.hello_world()

print(test.__name__)

When you execute this

python external_calling.py

Output

42
I am inside hello_world
test

So, above is self explanatory that when you call test from other script, if loop name in test.py will not execute.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top