Forståelse av `if __name__ == «__main__’` i Python
I denne veiledningen skal vi utforske funksjonaliteten og betydningen av `if __name__ == «__main__’` i Python-programmering.
Har du noen gang gått gjennom en Python-kodebase som består av flere moduler? Hvis svaret er ja, har du sannsynligvis støtt på `if __name__ == «__main__’`-betingelsen i en eller flere av modulene. I løpet av de neste minuttene skal vi avdekke hva denne betingelsen innebærer og se på et praktisk eksempel der den kan være svært nyttig.
La oss starte!
Hva betyr `__name__` i Python?
I Python refererer en modul til en `.py`-fil som inneholder definisjoner av funksjoner, kode som skal utføres, og mer. For eksempel, hvis vi har en fil som heter `hello_world.py`, vil vi referere til denne som `hello_world.py`-filen eller `hello_world`-modulen.
Når en Python-modul kjøres, setter Python-tolken verdier for en rekke spesialvariabler, og `__name__` er en av dem. For å forstå betydningen av `__name__`, må man forstå hvordan import fungerer i Python.
📁 Last ned koden for denne delen her.
Gå til mappen `eksempel-1`. Der finner du filen `module1.py`. Variabelen `__name__` eksisterer i navnerommet til den aktive modulen.
Denne modulen skriver ut en tekstlinje, etterfulgt av verdien av variabelen `__name__`.
# example-1/module1.py print("Dette er module1.") print(f"Variabelen __name__ i module 1 er: {__name__}.")
La oss nå kjøre `module1` fra kommandolinjen.
$ python module1.py
I utdataene ser vi at variabelen `__name__` er satt til `__main__`.
Dette er module1. Variabelen __name__ i module 1 er: __main__.
Importere moduler i Python
I tillegg til å kjøre en Python-modul direkte, kan det være ønskelig å bruke funksjoner fra en annen modul i den nåværende. Python tillater dette gjennom import.
Importer gjør det mulig å gjenbruke funksjonaliteten i en annen modul, ved å inkludere den i gjeldende moduls omfang, uten å måtte gjenskape koden.
Filen `module2.py` inneholder følgende. Vi har importert `module1` inn i `module2`.
# example-1/module2.py import module1 # module1 er importert print(f"Dette er module2") print(f"Variabelen __name__ i module2 er: {__name__}.")
Vi kjører `module2.py` og observerer utdataene.
$ python module2.py
I utdataene nedenfor ser vi:
- `module1` kjøres i bakgrunnen når vi importerer den i `module2`, og den tilhørende utskriften blir vist.
- Men denne gangen er variabelen `__name__` ikke `__main__`, men `module1`.
- Siden vi kjørte `module2` direkte, er `__name__`-variabelen tilsvarende `module2` nå `__main__`.
Utdata: Dette er module1. Variabelen __name__ i module 1 er: module1. Dette er module2 Variabelen __name__ i module2 er: __main__.
💡 Viktig å huske:
– Hvis en modul kjøres direkte, blir variabelen `__name__` satt til `__main__`.
– Hvis en modul importeres i en annen modul, settes dens `__name__` til navnet på modulen.
Eksempel på `if __name__ == «__main__’` i Python
I dette avsnittet skal vi undersøke et praktisk bruksområde for `if __name__ == «__main__’`-betingelsen. Vi definerer en enkel funksjon og deretter skriver vi enhetstester for å forsikre oss om at funksjonen fungerer som forventet.
📁 Last ned koden og følg med.
Koden for denne delen finner du i mappen `eksempel-2`.
`add.py` er en Python-fil som inneholder definisjonen av funksjonen `add_ab()`. Funksjonen `add_ab()` aksepterer to vilkårlige tall og returnerer summen av dem.
# example-2/add.py def add_ab(a,b): return a + b
Vi bruker Pythons `unittest`-modul for å teste funksjonen `add_ab()`.
Skrive testtilfeller for en Python-funksjon
Se på kodeutdraget nedenfor som inneholder innholdet i `test_add`-modulen.
# 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)
Koden ovenfor gjør følgende:
- Importerer Pythons innebygde `unittest`-modul.
- Importerer funksjonen `add_ab()` fra `add`-modulen.
- Definerer testklassen `TestAdd` og et sett med testtilfeller som metoder inne i testklassen.
For å sette opp enhetstester for koden din, bør du først definere en testklasse som arver fra `unittest.TestCase`. Alle testtilfeller skal spesifiseres som metoder i klassen og bør begynne med `test_`.
Merk: Hvis metodene dine ikke er navngitt som `test_
La oss nå prøve å kjøre `test_add`-modulen fra terminalen.
$ python test_add.py
Du vil observere at det ikke er noen utdata, og at ingen av testene har blitt utført.
Hvorfor er det slik? 🤔
Dette skyldes at for å kjøre enhetstestene, må du kjøre `unittest` som hovedmodulen mens du utfører `test_add.py`, ved å bruke kommandoen nedenfor.
$ python -m unittest test_add.py
Når vi kjører kommandoen over, ser vi at alle de tre testene har blitt utført uten feil.
Utdata: ... ---------------------------------------------------------------------- Kjørte 3 tester på 0.000s OK
Det ville imidlertid vært mer praktisk om vi kunne kjøre testene når `test_add`-modulen kjøres, ikke sant? La oss finne ut hvordan vi kan oppnå dette i neste avsnitt.
Bruke `if __name__ == «__main__’` for å kjøre `unittest` som hovedmodul
Hvis du ønsker å kjøre alle enhetstestene når modulen kjøres direkte, kan du inkludere den betingede.
# 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) # Kjør unittest som hovedmodul if __name__ == '__main__': unittest.main()
Betingelsen i kodebiten ovenfor forteller Python-tolken at dersom denne modulen kjøres direkte, skal koden inne i blokken utføres, dvs. `unittest.main()`.
Du kan nå kjøre `test_add`-modulen etter å ha lagt til de to foregående kodelinjene.
$ python test_add.py
▶️ Når du kjører `test_add`-modulen direkte nå, vil alle de tre testene vi definerte utføres.
Utdata: ... ---------------------------------------------------------------------- Kjørte 3 tester på 0.000s OK
Utdataet over viser `OK`, som indikerer at alle testene har blitt kjørt uten feil. De tre prikkene `…` indikerer at tre tester har blitt kjørt, og at alle har bestått.
La oss nå endre den forventede returverdien for `test_add_1_minus7` til `8`. Siden funksjonen returnerer `-6` i dette tilfellet, bør dette resultere i en feilet test.
def test_add_1_minus7(self): self.assertEqual(add_ab(1,-7), 8)
Som vist i utdataet nedenfor, får vi `.F.`, av de tre testene, mislyktes en av dem (den andre testen), og i tilbakesporingen får vi en `AssertionError` som sier `-6 != 8`.
Utdata: .F. ====================================================================== FEIL: test_add_1_minus7 (__main__.TestAdd) ---------------------------------------------------------------------- Tilbakesporing (mest nylig kalt sist): Fil "test_add.py", linje 12, i test_add_1_minus7 self.assertEqual(add_ab(1,-7), 8) AssertionError: -6 != 8 ---------------------------------------------------------------------- Kjørte 3 tester på 0.021s FEIL (feil=1)
Det er viktig å merke seg at testene ikke nødvendigvis kjøres i den rekkefølgen de er definert i testklassen. I eksemplet over er `test_add_1_minus7` definert som den tredje metoden i testklassen, men den tilhørende testen ble kjørt som nummer to.
Oppsummering
Jeg håper denne veiledningen har hjulpet deg med å forstå hvordan `if __name__ == «__main__’`-betingelsen fungerer i Python.
Her er en rask oppsummering av de viktigste punktene:
- Python-tolken setter variabelen `__name__` før et Python-skript kjøres.
- Når du kjører en modul direkte, er verdien av `__name__` satt til `__main__`.
- Når du importerer en modul i et annet Python-skript, er verdien av `__name__` lik modulnavnet.
- Du kan bruke `if __name__ == «__main__’` for å kontrollere hvilke deler av modulen som kjøres under henholdsvis direkte og importerte utførelser.
Som neste steg kan du sjekke ut denne dybdeveiledningen om Python-sett. Lykke til med læringen! 🎉