Ko dara 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))
Ikreiz, kad Python tulks nolasa avota failu, tas veic divas darbības:
__vārds__
, un pēc tam__name__
pārbaudēm, ko mēs vienmēr redzam Python skriptos.
Koda paraugsLai izpētītu, kā darbojas imports un skripti, izmantosim nedaudz atšķirīgu koda paraugu. Pieņemsim, ka failā ar nosaukumu foo.py
ir šāds ieraksts.
# 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")
Kad Python interpeter nolasa avota failu, tas vispirms definē dažus īpašus mainīgos. Šajā gadījumā mums ir svarīgs mainīgais __name__
.
Kad jūsu modulis ir galvenā programma
Ja jūsu modulis (avota fails) tiek palaists kā galvenā programma, piem.
python foo.py
tulkojums piešķirs mainīgajam __vārds__
"__main__"`` kodēto virkni, t.i.,
name``.
# It's as if the interpreter inserts this at the top
# of your module when run as the main program.
__name__ = "__main__"
Kad jūsu moduli importē cits modulis No otras puses, pieņemsim, ka kāds cits modulis ir galvenā programma un tas importē jūsu moduli. Tas nozīmē, ka galvenajā programmā vai kādā citā modulī, ko importē galvenā programma, ir šāds paziņojums:
# Suppose this is in some other main program.
import foo
Šādā gadījumā tulks apskatīs jūsu moduļa foo.py
faila nosaukumu, atdalīs .py
un šo virkni piešķirs jūsu moduļa mainīgajam __name__
, t.i.
# It's as if the interpreter inserts this at the top
# of your module when it's imported from another module.
__name__ = "foo"
Pēc speciālo mainīgo iestatīšanas tulks izpilda visu moduļa kodu pa vienam izteikumam. Lai varētu sekot līdzi šim skaidrojumam, iespējams, vēlēsieties atvērt vēl vienu logu sānos ar koda paraugu. Vienmēr
"pirms importēšanas"
(bez pēdiņām).math
moduli un piešķir to mainīgajam ar nosaukumu math
. Tas ir līdzvērtīgi import math
aizstāšanai ar šādu (ņemiet vērā, ka `import`` ir zema līmeņa Python funkcija, kas pieņem virkni un izraisa faktisko importēšanu):# Atrast un ielādēt moduli, ņemot vērā tā virknes nosaukumu "math",
# tad piešķir to lokālajam mainīgajam ar nosaukumu math.
math = __import__("math")
"pirms funkcijasA"
.def
bloku, izveidojot funkcijas objektu, un pēc tam piešķir šo funkcijas objektu mainīgajam ar nosaukumu funkcijaA
."pirms funkcijasB"
.def
bloks, izveidojot vēl vienu funkcijas objektu, pēc tam piešķirot to mainīgajam ar nosaukumu funkcijaB
."pirms __name__ guard"
.
Tikai tad, ja jūsu modulis ir galvenā programma__name__
patiešām ir iestatīts uz "__main__"
, un tā izsauks abas funkcijas, izdrukājot virknes "Funkcija A"
un "Funkcija B 10.0"
.
Tikai tad, ja jūsu moduli importē cits modulis__name__
būs "foo"
, nevis "__main__"
, un tiks izlaista if
paziņojuma būtība.
Vismēr"pēc __name__ aizsargs"
.
Kopsavilkums
Apkopojot, šeit ir aprakstīts, kas tiks izdrukāts abos gadījumos:
# 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
Jums, protams, varētu rasties jautājums, kāpēc kāds to vēlētos. Dažreiz jūs vēlaties uzrakstīt .py
failu, ko var izmantot citas programmas un/vai moduļi kā moduli, un ko var palaist arī kā galveno programmu. Piemēri:
Jūsu modulis ir bibliotēka, bet jūs vēlaties, lai tas darbotos skripta režīmā, kurā tiek palaisti daži vienības testi vai demo.
Jūsu modulis tiek izmantots tikai kā galvenā programma, bet tajā ir daži vienību testi, un testēšanas ietvars darbojas, importējot .py
failus, piemēram, jūsu skriptu, un palaižot īpašas testu funkcijas. Jūs nevēlaties, lai tas mēģinātu palaist skriptu tikai tāpēc, ka tas importē moduli.
Jautājums: Vai man var būt vairāki __name__
pārbaudes bloki? Atbilde: Tas'ir dīvaini, bet valoda jūs neapturēs.
Pieņemsim, ka foo2.py
ir šāds bloks. Kas notiks, ja komandrindā pateiksiet python foo2.py
? Kāpēc?
# 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__
pārbaudi foo3.py
:# 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")
Kad skripts tiek palaists, nododot to kā komandu Python interpretatoram,
python myscript.py
tiek izpildīts viss kods, kas ir 0 ievilkuma līmenī. Definētās funkcijas un klases ir definētas, kā arī ir definētas, bet neviens no to kodiem netiek izpildīts. Atšķirībā no citām valodām šeit nav main()
funkcijas, kas tiek automātiski izpildīta - main()
funkcija ir viss augšējā līmeņa kods.
Šajā gadījumā augstākā līmeņa kods ir if
bloks. __name__
ir iebūvēts mainīgais, kura vērtība ir pašreizējā moduļa nosaukums. Tomēr, ja modulis tiek palaists tieši (kā myscript.py
iepriekš), tad __name__
tiek iestatīts uz virkni "__main__"
. Tādējādi jūs varat pārbaudīt, vai jūsu skripts tiek palaists tieši vai importēts ar kaut ko citu, testējot
if __name__ == "__main__":
...
Ja jūsu skripts tiek importēts citā modulī, tā dažādās funkciju un klašu definīcijas tiks importētas un tā augstākā līmeņa kods tiks izpildīts, bet kods, kas ir iepriekš minētā if
klauzulas "then" ķermenī, netiks izpildīts, jo nosacījums nav izpildīts. Kā pamata piemēru aplūkojiet šādus divus skriptus:
# 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")
Tagad, ja jūs izsaucat tulku kā
python one.py
Izvades rezultāts būs šāds
top-level in one.py
one.py is being run directly
Ja tā vietā palaidīsiet two.py
:
python two.py
Jūs saņemat
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
Tādējādi, ielādējot moduli one
, tā __name__
ir "one"
, nevis "__main__"
.
if __name__ == "__main__"
ir daļa, kas tiek palaista, kad skripts tiek palaists no (teiksim) komandrindas, izmantojot komandu, piemēram, python myscript.py
.