Разбиране дали __name__ == ‘__main__’ в Python

В това ръководство ще разберете функционалността и значението на if __name__ == ‘__main__’ в Python.

Преглеждали ли сте някога кодова база на Python с различни модули?

Ако отговорът е да, вероятно бихте попаднали на if __name__ == ‘__main__’ условно в един или повече модули. През следващите няколко минути ще демистифицираме какво означава горното условно условие и ще разгледаме пример, където може да бъде полезно.

Нека да започнем!

Какво е значението на __name__ в Python?

В Python модулът е .py файл, който съдържа дефиниции на функции, набор от изрази, които трябва да бъдат оценени, и други. Например, ако имаме файл с име hello_world.py, ние го наричаме файл hello_world.py или модул hello_world.

Когато изпълнявате модул на Python, интерпретаторът на Python задава стойностите за няколко специални променливи преди изпълнението: __name__ е една от тях. Ключът към разбирането на значението на __name__ е разбирането как импортирането работи в Python.

📁 Изтеглете кода за този раздел тук.

Преминете към папката example-1. Имаме файла module1.py. Променливата __name__ е в пространството от имена на текущия модул.

Този модул отпечатва ред, последван от стойността на променливата __name__.

# example-1/module1.py
print("This is module1.")
print(f"The __name__ variable of module 1 is: {__name__}.")

Сега нека стартираме module1 от командния ред.

$ python module1.py

В изхода виждаме, че променливата __name__ е зададена на __main__.

This is module1.
The __name__ variable of module 1 is: __main__.

Импортиране на модули в Python

В допълнение към изпълнението на Python модул, понякога може да искате да използвате функционалност от друг Python модул вътре в текущия модул. Python улеснява това чрез импортиране.

  Как да създадете книга в Microsoft Word

Импортирането ви позволява да използвате повторно функционалността на друг модул – като го импортирате в обхвата на текущия модул – без да се налага да пренаписвате кода.

Файлът module2.py съдържа следното. Имаме импортиран модул1 вътре. модул2.

# example-1/module2.py

import module1 # module1 is imported

print(f"This is module2")
print(f"The __name__ variable of module2 is: {__name__}.")

Изпълняваме module2.py и наблюдаваме изхода.

$ python module2.py

В резултата по-долу:

  • Виждаме, че module1 се изпълнява под капака, когато го импортираме в module2, и съответният изход се отпечатва.
  • Но този път променливата __name__ не е __main__, а module1.
  • Тъй като изпълнихме module2 директно, променливата __name__, съответстваща на модула, сега е __main__.
Output

This is module1.
The __name__ variable of module 1 is: module1.
This is module2
The __name__ variable of module2 is: __main__.

💡 Ключова идея:

– Ако даден модул се изпълнява директно, неговата променлива __name__ е зададена на е равна на __main__.

– Ако модул е ​​импортиран в друг модул, неговото __name__ е зададено на името на модула.

Пример за if __name__==’__main__’ в Python

В раздела ще видим случай на практическа употреба на условния if __name__ == ‘__main__’. Ще дефинираме проста функция и след това ще напишем модулни тестове, за да проверим дали функцията работи според очакванията.

📁 Изтеглете кода и следвайте.

Кодът за този раздел може да бъде намерен в папката example-2.

Тук add.py е файл на Python, който съдържа дефиницията на функцията add_ab(). Функцията add_ab() приема произволни две числа и връща тяхната сума.

# example-2/add.py

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

Ще използваме модула unittest на Python, за да тестваме функцията add_ab().

Писане на тестови случаи за функция на Python

Вижте кодовия фрагмент по-долу, съдържащ съдържанието на модула test_add.

# example-2/test_add.py

import unittest
from add import add_ab

class TestAdd(unittest.TestCase):
    def test_add_23(self):
        self.assertEqual(add_ab(2,3), 5)
    
    def test_add_19(self):
        self.assertEqual(add_ab(1,9), 10)
    
    def test_add_1_minus7(self):
        self.assertEqual(add_ab(1,-7), -6)
    

Горният код прави следното:

  • Импортира вградения модул unittest на Python
  • Импортира функцията add_ab() от модула за добавяне
  • Дефинира тестовия клас TestAdd и набор от тестови случаи като методи в тестовия клас
  Как да прехвърлите данни от стария си компютър към новия си Mac

За да настроите модулни тестове за вашия код, първо трябва да дефинирате тестов клас, който наследява от unittest.TestCase. Всички тестови случаи трябва да бъдат посочени като методи в класа и трябва да започват с test_.

Забележка: Ако не посочите методите като test_, ще видите, че съответните тестове няма да бъдат открити и следователно няма да се изпълняват.

Сега нека опитаме да изпълним модула test_add от терминала.

$ python test_add.py

Ще видите, че няма резултат и нито един от тестовете не е изпълнен.

Защо е така?🤔

Това е така, защото за да стартирате модулните тестове, трябва да стартирате unittest като основен модул, докато изпълнявате test_add.py, като използвате командата по-долу.

$ python -m unittest test_add.py

При изпълнение на горната многословна команда виждаме, че и трите теста са извършени успешно.

Output
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK

Въпреки това ще бъде удобно да се изпълняват тестовете, когато се изпълнява този модул test_add, нали? Нека научим как да го направим в следващия раздел.

Използване на if __name__ == ‘__main__’ за изпълнение на unittest като основен модул

Ако искате да изпълните всички модулни тестове, когато модулът се изпълнява директно, можете да добавите условното.

# example-2/test_add.py

import unittest
from add import add_ab

class TestAdd(unittest.TestCase):
    def test_add_23(self):
        self.assertEqual(add_ab(2,3), 5)
    
    def test_add_19(self):
        self.assertEqual(add_ab(1,9), 10)
    
    def test_add_1_minus7(self):
        self.assertEqual(add_ab(1,-7), -6)

# Run unittest as the main module
if __name__ == '__main__':
        unittest.main()

Условният елемент в горния кодов фрагмент казва на интерпретатора на Python: Ако този модул се стартира директно, изпълнете кода вътре. unittest.main().

  Най-добрите алтернативи на Nagios за мрежов мониторинг

Можете да стартирате модула test_add, след като добавите горните два реда код.

$ python test_add.py

▶️ Директното изпълнение на модула за добавяне на тест сега изпълнява и трите теста, които сме дефинирали.

Output
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK

Горният резултат OK показва, че всички тестове са изпълнени успешно. Трите точки … показват, че са проведени три теста и всички са преминали.

Сега нека променим очакваната върната стойност test_add_1_minus7 на 8. Тъй като функцията връща – 6 в този случай, трябва да има един неуспешен тест.

def test_add_1_minus7(self):
        self.assertEqual(add_ab(1,-7), 8)

Както се вижда в изхода по-долу, получаваме .F., от трите теста, моделът на един от тях е неуспешен (вторият тест), а в проследяването получаваме AssertionError, заявяващ – 6 != 8.

Output
.F.
======================================================================
FAIL: test_add_1_minus7 (__main__.TestAdd)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_add.py", line 12, in test_add_1_minus7
    self.assertEqual(add_ab(1,-7), 8)
AssertionError: -6 != 8

----------------------------------------------------------------------
Ran 3 tests in 0.021s

FAILED (failures=1)

Едно важно нещо, което трябва да се отбележи, е, че тестовете не се изпълняват непременно в същия ред, в който са посочени в тестовия клас. В горния пример test_add_1_minus7 е дефиниран като трети метод в тестовия клас, но съответният тест е изпълнен втори.

Обобщаване

Надявам се, че този урок ви е помогнал да разберете как работи условието if __name__ == ‘__main__’ в Python.

Ето кратко резюме на основните изводи:

  • Интерпретаторът на Python задава променливата __name__ преди да изпълни скрипта на Python.
  • Когато стартирате модул директно, стойността на __name__ е __main__.
  • Когато импортирате модул в друг скрипт на Python, стойността на __name__ е името на модула.
  • Можете да използвате if __name__ == ‘__main__’, за да контролирате изпълнението и кои части от модула се изпълняват съответно по време на директно и импортирано изпълнение.

След това вижте това задълбочено ръководство за набори на Python. Приятно учене!🎉