Ko dara if __name__ == "__main__":?

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))
Risinājums

Ikreiz, kad Python tulks nolasa avota failu, tas veic divas darbības:

  • tas nosaka dažus īpašus mainīgos, piemēram, __vārds__, un pēc tam
  • izpilda visu failā atrodamo kodu.

Aplūkosim, kā tas darbojas un kā tas ir saistīts ar jūsu jautājumu par __name__ pārbaudēm, ko mēs vienmēr redzam Python skriptos. Koda paraugs

Lai 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")

Īpašie mainīgie

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"

Moduļa's koda izpilde

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

  1. Tas izdrukā virkni "pirms importēšanas" (bez pēdiņām).
  2. Tā ielādē 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")
  3. Tas izraksta virkni "pirms funkcijasA".
  4. Tas izpilda def bloku, izveidojot funkcijas objektu, un pēc tam piešķir šo funkcijas objektu mainīgajam ar nosaukumu funkcijaA.
  5. Tas izdrukā virkni "pirms funkcijasB".
  6. Tiek izpildīts otrais def bloks, izveidojot vēl vienu funkcijas objektu, pēc tam piešķirot to mainīgajam ar nosaukumu funkcijaB.
  7. Tas izdrukā virkni "pirms __name__ guard". Tikai tad, ja jūsu modulis ir galvenā programma
  8. Ja jūsu modulis ir galvenā programma, tad tā redzēs, ka __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
  9. (Ja jūsu modulis nav galvenā programma, bet ir importēts no citas programmas, tad __name__ būs "foo", nevis "__main__", un tiks izlaista if paziņojuma būtība. Vismēr
  10. Tas abās situācijās izdrukās virkni "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

Kāpēc tas tā darbojas?

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.

  • Jūsu modulis lielākoties tiek izmantots kā galvenā programma, taču tas nodrošina arī programmētājam draudzīgu API pieredzējušiem lietotājiem. Papildus šiem piemēriem, tas ir elegants, ka skripta palaišana Python ir tikai dažu maģisko mainīgo iestatīšana un skripta importēšana. "Skripta palaišana" ir skripta moduļa importēšanas blakus efekts. Pārdomu viela

  • 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")
  • Tagad noskaidrojiet, kas notiks, ja noņemsiet __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")
  • Ko tas darīs, ja to izmantos kā skriptu? Kad importēts kā modulis?
# Suppose this is in foo4.py
__name__ = "__main__"

def bar():
    print("bar")

print("before __name__ guard")
if __name__ == "__main__":
    bar()
print("after __name__ guard")
Komentāri (6)

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__".

Komentāri (0)

if __name__ == "__main__" ir daļa, kas tiek palaista, kad skripts tiek palaists no (teiksim) komandrindas, izmantojot komandu, piemēram, python myscript.py.

Komentāri (1)