В това ръководство ще разберете функционалността и значението на 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 улеснява това чрез импортиране.
Импортирането ви позволява да използвате повторно функционалността на друг модул – като го импортирате в обхвата на текущия модул – без да се налага да пренаписвате кода.
Файлът 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 и набор от тестови случаи като методи в тестовия клас
За да настроите модулни тестове за вашия код, първо трябва да дефинирате тестов клас, който наследява от 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().
Можете да стартирате модула 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. Приятно учене!🎉