Pochopení if __name__ == ‚__main__‘ v Pythonu

Photo of author

By etechblogcz

V tomto průvodci se podíváme na to, jak funguje a jaký význam má konstrukce if __name__ == '__main__' v programovacím jazyce Python.

Setkali jste se již někdy s kódem v Pythonu, který obsahoval různé moduly?

Pokud ano, je velmi pravděpodobné, že jste narazili na podmínku __name__ == '__main__' v některém z těchto modulů. Během následujících minut si vysvětlíme, co tato podmínka znamená, a prozkoumáme příklad, kde může být užitečná.

Začněme!

Co představuje proměnná __name__ v Pythonu?

V Pythonu je modul soubor s příponou .py, který obsahuje definice funkcí, výrazy a další elementy. Například, pokud máme soubor s názvem hello_world.py, označujeme ho jako modul hello_world.

Když spouštíte modul v Pythonu, interpret před spuštěním nastaví hodnoty několika speciálních proměnných. Proměnná __name__ je jednou z nich. Klíčem k pochopení jejího významu je pochopení, jak funguje import modulů v Pythonu.

📁 Stáhněte si ukázkový kód z této sekce zde.

Přejděte do složky example-1. Zde se nachází soubor module1.py. Proměnná __name__ je součástí jmenného prostoru aktuálního modulu.

Tento modul vypíše jeden řádek textu a za ním hodnotu proměnné __name__.

    # example-1/module1.py
    print("Toto je modul 1.")
    print(f"Proměnná __name__ v modulu 1 má hodnotu: {__name__}.")
  

Nyní spusťte module1 z příkazového řádku.

    $ python module1.py
  

Ve výstupu vidíme, že proměnná __name__ má nastavenou hodnotu __main__.

    Toto je modul 1.
    Proměnná __name__ v modulu 1 má hodnotu: __main__.
  

Import modulů v Pythonu

Kromě spouštění modulů můžete chtít použít funkce z jiných modulů v rámci aktuálního modulu. Python toto umožňuje díky importům.

Importy umožňují opětovně využít funkce z jiného modulu, aniž by bylo nutné psát kód znovu.

Soubor module2.py obsahuje následující. V něm importujeme module1.

    # example-1/module2.py
    import module1 # module1 je importován

    print(f"Toto je modul 2")
    print(f"Proměnná __name__ v modulu 2 má hodnotu: {__name__}.")
  

Spustíme module2.py a podíváme se na výstup.

    $ python module2.py
  

Ve výstupu:

  • Vidíme, že module1 se spustí při importování do module2 a vytiskne odpovídající výstup.
  • Proměnná __name__ tentokrát není __main__, ale má hodnotu module1.
  • Protože jsme přímo spustili modul module2, proměnná __name__ odpovídající tomuto modulu je __main__.
    Výstup:
    Toto je modul 1.
    Proměnná __name__ v modulu 1 má hodnotu: module1.
    Toto je modul 2
    Proměnná __name__ v modulu 2 má hodnotu: __main__.
  

💡 Klíčové body:

– Pokud je modul spuštěn přímo, jeho proměnná __name__ má hodnotu __main__.

– Pokud je modul importován do jiného modulu, jeho proměnná __name__ má hodnotu názvu modulu.

Příklad if __name__ == '__main__' v Pythonu

V této části se podíváme na praktický příklad použití podmínky if __name__ == '__main__'. Definujeme jednoduchou funkci a poté k ní napíšeme jednotkové testy.

📁 Stáhněte si kód a postupujte podle pokynů.

Kód pro tuto sekci najdete ve složce example-2.

Soubor add.py je pythonovský soubor, který obsahuje definici funkce add_ab(). Funkce add_ab() přijímá dvě čísla a vrací jejich součet.

    # example-2/add.py
    def add_ab(a, b):
        return a + b
  

K testování funkce add_ab() použijeme modul unittest z Pythonu.

Psaní testovacích případů pro funkci v Pythonu

Níže si prohlédněte kód, který obsahuje obsah modulu 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)
  

Výše uvedený kód dělá následující:

  • Importuje vestavěný modul unittest z Pythonu.
  • Importuje funkci add_ab() z modulu add.
  • Definuje testovací třídu TestAdd a sadu testovacích případů jako metody uvnitř této třídy.

Chcete-li pro svůj kód vytvořit jednotkové testy, měli byste nejdříve definovat testovací třídu, která dědí z unittest.TestCase. Všechny testovací případy by měly být specifikovány jako metody uvnitř třídy a měly by začínat prefixem test_.

Poznámka: Pokud metody nepojmenujete jako test_<nějaký-popisný-název>, odpovídající testy nebudou detekovány a nebudou spuštěny.

Zkusme nyní spustit modul test_add z terminálu.

    $ python test_add.py
  

Uvidíme, že se nevypíše žádný výstup a žádný z testů neproběhne.

Proč tomu tak je? 🤔

Je to proto, že pro spuštění jednotkových testů byste měli spustit unittest jako hlavní modul při spouštění test_add.py pomocí následujícího příkazu.

    $ python -m unittest test_add.py
  

Po spuštění tohoto příkazu vidíme, že všechny tři testy proběhly úspěšně.

    Výstup:
    ...
    ----------------------------------------------------------------------
    Ran 3 tests in 0.000s

    OK
  

Bylo by však praktické spouštět testy, když se modul test_add spustí přímo, že ano? V následující části se podíváme, jak na to.

Použití if __name__ == '__main__' ke spuštění unittest jako hlavního modulu

Pokud chcete, aby se všechny testy jednotek spustily, když se modul spouští přímo, můžete přidat podmínku.

    # 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)

    # Spustí unittest jako hlavní modul
    if __name__ == '__main__':
        unittest.main()
  

Podmínka ve výše uvedeném kódu říká interpretu Pythonu: Pokud se tento modul spouští přímo, spusť kód uvnitř – tedy unittest.main().

Nyní můžete modul test_add spustit po přidání výše uvedených dvou řádků kódu.

    $ python test_add.py
  

▶️ Přímé spuštění modulu pro přidání testu nyní spustí všechny tři testy, které jsme definovali.

    Výstup:
    ...
    ----------------------------------------------------------------------
    Ran 3 tests in 0.000s

    OK
  

Výše uvedený výstup OK znamená, že všechny testy proběhly úspěšně. Tři tečky ... naznačují, že byly provedeny tři testy a všechny prošly.

Nyní změníme očekávanou návratovou hodnotu testu test_add_1_minus7 na 8. Protože funkce v tomto případě vrací -6, jeden test by měl selhat.

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

Jak je vidět na výstupu, dostaneme .F., ze tří testů jeden selhal (druhý test) a v tracebacku dostaneme AssertionError, který uvádí, že -6 != 8.

    Výstup:
    .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)
  

Je důležité si uvědomit, že testy nemusí běžet nutně ve stejném pořadí, v jakém jsou uvedeny v testovací třídě. V tomto příkladu je test_add_1_minus7 definován jako třetí metoda v testovací třídě, ale odpovídající test se spustil jako druhý.

Shrnutí

Doufám, že vám tento tutoriál pomohl pochopit, jak podmínka if __name__ == '__main__' funguje v Pythonu.

Zde je stručný přehled klíčových informací:

  • Interpret Pythonu nastaví proměnnou __name__ před spuštěním skriptu.
  • Když spustíte modul přímo, hodnota __name__ je __main__.
  • Když importujete modul do jiného skriptu, hodnota __name__ se rovná názvu modulu.
  • Můžete použít if __name__ == '__main__' ke kontrole toho, které části modulu se mají spustit při přímém spuštění a importu.

Podívejte se také na tohoto detailního průvodce o sadách v Pythonu. Příjemné učení! 🎉