Mit csinál a 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))
Amikor a Python-értelmező beolvas egy forrásfájlt, két dolgot tesz:
__name__
, és aztán__name__
ellenőrzésekkel kapcsolatos kérdésedhez.
KódmintaHasználjunk egy kissé eltérő kódmintát, hogy megvizsgáljuk, hogyan működnek az importok és a szkriptek. Tegyük fel, hogy az alábbiakat egy foo.py
nevű fájlban találjuk.
# 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")
Amikor a Python interpeter beolvas egy forrásfájlt, először definiál néhány speciális változót. Ebben az esetben a __név__
változóval foglalkozunk.
Ha a modulod a főprogram
Ha a modulodat (a forrásfájlt) főprogramként futtatod, pl.
python foo.py
az értelmező a __name__
változóhoz hozzárendeli a "__main__"
keményen kódolt "__main__"
karakterláncot, azaz.
# It's as if the interpreter inserts this at the top
# of your module when run as the main program.
__name__ = "__main__"
Ha a modulodat egy másik importálja Másrészt tegyük fel, hogy egy másik modul a főprogram, és az importálja a te modulodat. Ez azt jelenti, hogy a főprogramban, vagy egy másik modulban, amelyet a főprogram importál, van egy ilyen utasítás:
# Suppose this is in some other main program.
import foo
Ebben az esetben az értelmező megnézi a modulod fájlnevét, a foo.py
-t, eltávolítja a .py
-t, és ezt a karakterláncot hozzárendeli a modulod __name__
változójához, azaz.
# It's as if the interpreter inserts this at the top
# of your module when it's imported from another module.
__name__ = "foo"
A speciális változók beállítása után az értelmező a modul összes kódját végrehajtja, utasításonként. Érdemes egy másik ablakot nyitni a kódminta oldalán, hogy követni tudja a magyarázatot. Mindig
"before import"
(idézőjelek nélkül) karakterláncot.math
modult, és hozzárendeli egy math
nevű változóhoz. Ez egyenértékű az import math
helyettesítésével a következőkkel (jegyezzük meg, hogy a __import__
egy alacsony szintű függvény a Pythonban, amely egy karakterláncot vesz fel, és elindítja a tényleges importálást):# Keressünk és töltsünk be egy modult a sztring nevével, "math",
# majd hozzárendeljük egy math nevű helyi változóhoz.
math = __import__("math")
"a függvényA"
előtti sztringet.def
blokkot, létrehoz egy függvényobjektumot, majd ezt a függvényobjektumot hozzárendeli a functionA
nevű változóhoz."before functionB"
karakterláncot.def
blokkot, létrehoz egy másik függvényobjektumot, majd hozzárendeli azt a functionB
nevű változóhoz."before __name__ guard"
karakterláncot.
Kizárólag akkor, ha a modul a főprogram__name__
valóban a "__main__"
értéket kapta, és meghívja a két függvényt, kiírva a "Function A"
és a "Function B 10.0"
karakterláncokat.
Csak ha a modulodat egy másik importálja__name__
"foo"
lesz, nem pedig "__main__"
, és kihagyja az if
utasítás testét.
Mindig"__name__ guard"
után következő sztringet.
Összefoglaló
Összefoglalva, itt'van, hogy mit nyomtatna ki a két esetben:
# 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
Természetesen felmerülhet a kérdés, hogy miért akarja ezt bárki is. Nos, néha olyan .py
fájlt akarsz írni, amelyet más programok és/vagy modulok egyaránt használhatnak modulként, és maga a főprogramként is futtatható. Példák:
A modulod egy könyvtár, de szeretnél egy szkript módot, ahol lefuttat néhány unit tesztet vagy egy demót.
A modulodat csak főprogramként használod, de van benne néhány egységteszt, és a tesztelési keretrendszer úgy működik, hogy a .py
fájlokat importálja, mint a szkripted, és speciális tesztfüggvényeket futtat. Nem akarod, hogy megpróbálja futtatni a szkriptet csak azért, mert a modult importálja.
Kérdés: Több __név__
ellenőrző blokk is lehet? Válasz: Ez'furcsa, de a nyelv nem fog meggátolni.
Tegyük fel, hogy a foo2.py
állományban van a következő. Mi történik, ha a parancssorban azt mondjuk, hogy python foo2.py
? Miért?
# 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__
ellenőrzést a `foo3.py'-ban:# 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")
A szkript futtatásakor a Python-értelmezőnek parancsként átadva,
python myscript.py
az összes olyan kód végrehajtásra kerül, amely a 0. behúzási szinten van. A definiált függvények és osztályok, nos, definiálva vannak, de egyikük kódja sem fut le. Más nyelvektől eltérően nincs main()
függvény, amely automatikusan lefut - a main()
függvény implicit módon az összes kód a legfelső szinten.
Ebben az esetben a legfelső szintű kód egy if
blokk. A __név__
egy beépített változó, amely az aktuális modul nevére értékelődik ki. Ha azonban egy modult közvetlenül futtatunk (mint a fenti myscript.py
-ban), akkor a __name__
helyette a "__main__"
karakterláncot kapja. Így tesztelheted, hogy a szkripted közvetlenül fut-e, vagy valami más importálja, a következő teszteléssel
if __name__ == "__main__":
...
Ha a szkriptet egy másik modulba importálják, akkor a különböző függvény- és osztálydefiníciói importálásra kerülnek, és a felső szintű kódja végrehajtásra kerül, de a fenti if
záradék then-testében lévő kód nem fog lefutni, mivel a feltétel nem teljesül. Alapvető példaként tekintsük a következő két szkriptet:
# 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")
Most, ha meghívjuk az értelmezőt mint
python one.py
A kimenet a következő lesz
top-level in one.py
one.py is being run directly
Ha helyette a two.py
t futtatod:
python two.py
Azt kapod, hogy
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
Így amikor az egy
modul betöltődik, a __name__
egyenlő "one"
"main"` helyett.
if __name__ == "__main__"
az a rész, amely akkor fut le, ha a szkriptet (mondjuk) a parancssorból futtatjuk egy olyan paranccsal, mint a python myscript.py
.