Soru __Name__ == “__main__” ise ne yapar?


Ne yapar if __name__ == "__main__": yap?

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

4149
2018-01-07 04:11


Menşei




Cevaplar:


Python yorumlayıcısı bir kaynak dosya okuduğunda, içinde bulunan tüm kodları çalıştırır.

Kodu çalıştırmadan önce, birkaç özel değişken tanımlayacaktır. Örneğin, Python yorumlayıcısı bu modülü (kaynak dosya) ana program olarak çalıştırıyorsa, özel olarak ayarlar. __name__ bir değere sahip değişken "__main__". Bu dosya başka bir modülden içe aktarılıyorsa, __name__ modülün adına ayarlanacaktır.

Komut dosyanızın durumunda, ana işlev olarak çalışacağını varsayalım. hoşuna gittin

python threading_example.py

komut satırında. Özel değişkenleri ayarladıktan sonra, import deyim ve bu modülleri yükler. Daha sonra değerlendirecek def blok, bir fonksiyon nesnesi oluşturmak ve denen bir değişken oluşturmak myfunction Bu işlev nesnesine işaret eder. Daha sonra okuyacaktır if açıkla ve gör __name__ eşittir "__main__"Bu yüzden orada gösterilen bloğu çalıştıracaktır.

Bunu yapmanın bir nedeni, bazen bir modül yazmanızdır (bir .py dosya) doğrudan yürütülebilmektedir. Alternatif olarak, başka bir modülde de içe aktarılabilir ve kullanılabilir. Ana kontrolü yaparak, bu kodu yalnızca modülü bir program olarak çalıştırmak istediğinizde çalıştırabilirsiniz ve birisi sadece modülünüzü almak ve işlevlerinizi kendileri çağırmak istediğinde çalıştırılamaz.

Görmek bu sayfa bazı ekstra detaylar için.


4421
2018-01-07 04:26



Not: Eğer kodları işlev tanımlarından önce koyarsanız, ana işlemden önce çalışır. print("This code executes before main.") def functionA(): print("Function A") def functionB(): print("Function B") if __name__ == '__main__': functionA() functionB()  Bu kod şöyle sonuçlanır: This code executes before main. Function A Function B - Stainsor


Komut dosyanız Python yorumlayıcısına bir komut olarak iletilerek çalıştırılıyorsa,

python myscript.py

Girinti seviyesi 0 olan tüm kod yürütülür. Tanımlanan işlevler ve sınıflar iyi tanımlanmış, ancak kodlarının hiçbiri çalışmaz. Diğer dillerin aksine, yok main() otomatik olarak çalıştırılan işlev - main() İşlev, üst düzeydeki tüm kodları dolaylı olarak kapsamaktadır.

Bu durumda, üst düzey kod bir if blok. __name__ Mevcut modülün adını değerlendiren yerleşik bir değişkendir. Ancak, bir modül doğrudan çalıştırılıyorsa ( myscript.py yukarıda) __name__ bunun yerine dizeye ayarlandı "__main__". Böylece, komut dosyanızın doğrudan çalıştırıldığını veya test ederek başka bir şey tarafından içe aktarıldığını test edebilirsiniz.

if __name__ == "__main__":
    ...

Eğer betiğiniz başka bir modüle içe aktarılıyorsa, çeşitli işlevleri ve sınıf tanımları içe aktarılacak ve en üst seviye kodu çalıştırılacaktır, ancak kodun o zamanki gövdesindeki kod if koşulu karşılanmadığı için yukarıdaki şart koşmaz. Temel bir örnek olarak, aşağıdaki iki betiği göz önünde bulundurun:

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

Şimdi, tercümanı

python one.py

Çıktı olacak

top-level in one.py
one.py is being run directly

Eğer koşarsan two.py yerine:

python two.py

Sen al

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

Böylece, modül olduğunda one yüklenir, onun __name__ eşittir "one" yerine "__main__".


1415
2018-01-07 04:28



Parlak açıklama. - Poles


İçin en basit açıklama __name__ değişken (imho) aşağıdaki gibidir:

Aşağıdaki dosyaları oluşturun.

# a.py
import b

ve

# b.py
print "Hello World from %s!" % __name__

if __name__ == '__main__':
    print "Hello World again from %s!" % __name__

Onları çalıştırmak size bu çıkışı verecek:

$ python a.py
Hello World from b!

Gördüğünüz gibi, bir modül alındığında, Python setleri globals()['__name__'] bu modülde modülün adına.

$ python b.py
Hello World from __main__!
Hello World again from __main__!

Gördüğünüz gibi, bir dosya yürütüldüğünde, Python setleri globals()['__name__'] bu dosyada "__main__".


562
2018-01-07 11:35





Ne yapar if __name__ == "__main__": yap?

Temelleri özetlemek için:

  • Küresel değişken __name__, programınıza giriş noktası olan modülde, '__main__'. Aksi takdirde, modülü tarafından içe aktardığınız ad budur.

  • Yani, altında kod if Blok sadece modül programınıza giriş noktası ise çalışır.

  • Modüldeki kodun, diğer modüller tarafından, ithalin altındaki kod bloğunu yürütmeksizin, ithal edilebilir olmasını sağlar.


buna neden ihtiyacımız var?

Kodunuzu Geliştirme ve Test Etme

Bir modül olarak kullanılmak üzere tasarlanmış bir Python komut dosyası yazdığını varsayalım:

def do_important():
    """This function does something very important"""

Sen could Fonksiyonun bu çağrısını aşağıya ekleyerek modülü test edin:

do_important()

ve bunun gibi bir şeye (komut isteminde)

~$ python important.py

Sorun

Ancak, modülü başka bir komut dosyasına almak isterseniz:

import important

İthalatta, do_important işlev çağrılırdı, bu yüzden muhtemelen işlev çağrınızı yorumlarsınız do_important(), altta.

# do_important() # I must remember to uncomment to execute this!

Ve sonra test fonksiyon çağrınızı açıklayıp yorumlamadığınızı hatırlamanız gerekecek. Ve bu ekstra karmaşıklık, muhtemelen unutmak, geliştirme sürecinizi daha zahmetli yapmak anlamına gelir.

En iyi yol

__name__ Python yorumlayıcısının bulunduğu anda ad alanlarına değişken noktalar.

İçe aktarılmış bir modülün içinde, bu modülün adı.

Ancak birincil modülün içinde (veya etkileşimli bir Python oturumu, yani yorumlayıcının Oku, Değerlendir, Yaz Döngüsü veya REPL), "__main__".

Yani, yürütmeden önce kontrol ederseniz:

if __name__ == "__main__":
    do_important()

Yukarıdaki kodla, kodunuz yalnızca birincil modül olarak çalıştırdığınızda yürütülür (veya başka bir komut dosyasından kasıtlı olarak adlandırılır).

Daha İyi Bir Yol

Bununla birlikte, bunu geliştirmek için Pythonic bir yolu var.

Bu iş sürecini modülün dışından çalıştırmak istersek ne olur?

Kodu koyarsak, bu şekilde bir işlev geliştirip test ettiğimizde egzersiz yapmak istiyoruz. '__main__' hemen sonra:

def main():
    """business logic for when running this module as the primary one!"""
    setup()
    foo = do_important()
    bar = do_even_more_important(foo)
    for baz in bar:
        do_super_important(baz)
    teardown()

# Here's our payoff idiom!
if __name__ == '__main__':
    main()

Modülü birincil modül olarak çalıştırırsak, modülümüzün son çalışması için şimdi son bir fonksiyonumuz var.

Modülü ve işlevlerini ve sınıflarını, çalıştırılmadan başka betiklere aktarılmasını sağlar. main işlev ve aynı zamanda farklı bir modülden çalışırken modülün (ve işlevlerinin ve sınıflarının) çağrılmasına izin verir '__main__' modül, yani

import important
important.main()

Bu deyim, Python belgelerinde de bir açıklamasında bulunabilir. __main__ modülü. Bu metin şöyle ifade eder:

Bu modül, (aksi halde anonim) kapsamını temsil eder.   yorumcunun ana programı yürütülür -   standart giriş, bir komut dosyasından veya etkileşimli bir istemden. O   deyimsel "koşullu senaryo" stanza'nın bulunduğu ortamdır   komut dosyasının çalıştırılmasına neden olur:

if __name__ == '__main__':
    main()

413
2017-11-23 04:38





if __name__ == "__main__"betik komut gibi çalıştırıldığında çalışan komut satırı gibi bir komut kullanarak komut satırı çalışır python myscript.py.


92
2018-01-07 04:14





Nedir if __name__ == "__main__": yap?

__name__ küresel bir değişkendir (Python'da, global aslında modül seviyesi) tüm ad alanlarında var. Tipik olarak modülün adıdır. str tipi).

Bununla birlikte, tek özel durum olarak, mycode.py'de olduğu gibi, Python işleminiz ne olursa olsun

python mycode.py

aksi halde anonim global isim alanı değeri atanır '__main__' onun için __name__.

Böylece, dahil son hatlar

if __name__ == '__main__':
    main()
  • mycode.py komut dosyanızın sonunda
  • Python işlemiyle çalıştırılan birincil, giriş noktası modülü olduğunda,

komut dosyanızın benzersiz olarak tanımlanmasına neden olacak main çalıştırmak için işlev.

Bu yapıyı kullanmanın bir başka yararı da: kodunuzu başka bir komut dosyasında bir modül olarak içe aktarabilir ve ardından program karar verirseniz ana işlevi çalıştırabilirsiniz:

import mycode
# ... any amount of other code
mycode.main()

57
2017-10-14 20:22





Söz konusu kodun mekaniği üzerinde çok farklı yollar var, "Nasıl", ama benim için hiçbiri "Neden" i anlayana kadar anlamsızdı. Bu yeni programcılar için özellikle yararlı olacaktır.

"Ab.py" dosyasını al:

def a():
    print('A function in ab file');
a()

Ve ikinci bir dosya "xy.py":

import ab
def main():
    print('main function: this is where the action is')
def x():
    print ('peripheral task: might be useful in other projects')
x()
if __name__ == "__main__":
    main()

Bu kod aslında ne yapıyor?

Çalıştırdığın zaman xy.py, sen import ab. İçe aktarma ifadesi modülü hemen içe aktarır. aboperasyonları geri kalanı önce idam edilmek xyVar. İle bittiğinde abile devam ediyor xy.

Tercüman, hangi komut dosyalarının çalıştığını takip eder __name__. Bir komut dosyasını çalıştırdığınızda - ne adlandırdığınız önemli değil - tercüman buna "__main__", harici bir komut dosyası çalıştırdıktan sonra döndürülecek ana veya 'ev' komut dosyası yapmak.

Bundan çağrılan başka bir senaryo "__main__" betik dosya adını kendi __name__ (Örneğin., __name__ == "ab.py"). Böylece çizgi if __name__ == "__main__": Başlangıçta çalıştırılan 'ev' betiğinin yorumlanıp / yorumlanmamasını veya geçici olarak başka bir (harici) senaryoya göz atıp açmadığını belirlemek için tercüman testi. Bu, doğrudan harici olarak adlandırılan çalıştırıldığında betiğin farklı davranmasını sağlamak için programcı esnekliğini verir.

Neyin olup bittiğini anlamak için, yukarıdaki kodları adım adım gösterelim, ilk önce girilmemiş satırlara ve komut dosyalarında göründükleri sıraya odaklanalım. Bu işlevi hatırla - veya def - bloklar arayana kadar kendiliğinden bir şey yapmazlar. Tercüman kendi kendine mırıldandığında ne diyebilir?

  • Xy.py dosyasını 'ev' dosyası olarak açın; Bunu aramak "__main__" içinde __name__ değişken.
  • İçe aktar ve dosyayı aç __name__ == "ab.py".
  • Ah, bir fonksiyon. Bunu hatırlayacağım.
  • Tamam, fonksiyon a(); Bunu yeni öğrendim. Baskı 'Ab dosyasındaki bir işlev'.
  • Dosyanın sonu; geri dön "__main__"!
  • Ah, bir fonksiyon. Bunu hatırlayacağım.
  • Bir diğeri.
  • fonksiyon x(); tamam, yazdırmaçevresel görev: diğer projelerde yararlı olabilir'.
  • Bu nedir? bir if Beyan. Eh, koşul karşılandı (değişken __name__ayarlandı "__main__"), ben gireceğim main() işlev ve yazdırmaana işlev: eylem burası'.

En alttaki iki satır: "Eğer bu "__main__" veya 'ev' betiği, çağrılan işlevi yürütmek main()".Bu yüzden bir def main(): komut dosyasının işlevselliğinin ana akışını içeren yukarı blok.

Bunu neden uygularsınız?

İçe aktarma ifadeleri hakkında daha önce söylediğimi hatırla? Bir modülü içe aktardığınızda, onu '' tanıyamaz '' ve daha fazla talimatı beklemez - aslında betik içindeki tüm çalıştırılabilir işlemleri çalıştırır. Yani, senaryonun etini main() işlevi, başka bir komut dosyası tarafından içe aktarıldığında hemen çalışmayacak şekilde yalıtımı etkin bir şekilde karantinaya alır.

Yine, istisnalar olacak, ancak ortak uygulama şu ki main() genellikle dışarıdan çağırılmaz. Yani bir şey daha merak ediyor olabilirsiniz: eğer aramıyorsak main()Neden senaryoyu çağırıyoruz? Bunun nedeni, birçok insanın betiklerini, dosyadaki kodun geri kalanından bağımsız olarak çalıştırılmak üzere oluşturulmuş bağımsız işlevlerle yapılandırmasıdır. Daha sonra senaryoların gövdesinde başka bir yere çağrılırlar. Bu bana şunu getirir:

Ama kod olmadan çalışır

Evet bu doğru. Bu ayrı fonksiyonlar kutu İçerisinde bulunmayan bir satır içi betikden çağrılabilir main() işlevi. Eğer alışkınsanız (benim programlama aşamasındayken, programlama sürecinin ilk aşamalarında), ihtiyacınız olan şeyi yapan satır içi komut dosyaları oluşturmaya devam edersiniz ve tekrar bu işleme ihtiyacınız olursa tekrar anlamaya çalışacaksınız. Peki, bu tür bir iç yapıya kodunuz için alışkın değilsiniz, çünkü daha karmaşık bir yapıya sahip ve okumak için sezgisel değil.

Ancak bu, muhtemelen dışsal olarak adlandırılan işlevlerine sahip olmayan bir komut dosyasıdır, çünkü eğer yapsaydı, hemen değişkenleri hesaplamaya ve atamaya başlayacaktı. Ve eğer bir işlevi yeniden kullanmaya çalışıyorsanız, yeni senaryonuz birbiriyle çelişen değişkenler olacak kadar yakındır.

Bağımsız işlevleri ayırırken, önceki çalışmalarınızı başka bir betiğe çağırarak yeniden kullanma yeteneğini kazanırsınız. Örneğin, "example.py", "xy.py" dosyasını içe aktarabilir ve arayabilir x()xy.py'den 'x' işlevini kullanmak. (Belki de belirli bir metin dizesinin üçüncü kelimesini sermayelemek, bir sayı listesinden bir NumPy dizisi oluşturmak ve bunları kare çizmek ya da bir 3B yüzeyi belirlemeyi. Olasılıklar sınırsızdır.)

(Bir kenara göre, bu soru nihayet anlamam için bana yardımcı olan @kindall tarafından bir cevap içeriyor - neden, nasıl değil. Maalesef bir kopyası olarak işaretlendi Buki bence bir hata.)


47
2017-09-29 04:33





Modülümüzde belirli ifadeler olduğunda (M.py) Ana olarak (ithal edilmediğinde) çalıştırılacağı zaman idam edilmek istiyoruz, bu ifadeleri (test senaryoları, baskı beyanları) ifblok.

Varsayılan olarak (modül ana olarak çalıştırıldığında, içe aktarılmadığında) __name__ değişken olarak ayarlandı "__main__"ve ne zaman alınacağını __name__ Değişken farklı bir değer elde edecek, büyük olasılıkla modülün adı ('M'). Bu, bir modülün farklı varyantlarını birlikte çalıştırırken ve özel girdi ve çıktı ifadelerini ayırmada ve ayrıca herhangi bir test vakası varsa yararlıdır.

Kısacası, bunu kullan 'if __name__ == "main" 'Modül alındığında (belirli) kodun çalışmasını engellemek için blok.


39
2018-04-03 14:09





Cevaba daha soyut bir şekilde bakalım:

Bu kodu x.py'de aldığımızı varsayalım:

...
<Block A>
if __name__ == '__main__':
    <Block B>
...

"X.py" çalıştırırken A ve B blokları çalıştırılır.

Ancak sadece bir blok (B değil, B), başka bir modül çalıştırırken çalıştırılır, örneğin, "y.py", xy içe aktarılır ve kod oradan çalıştırılır ("x.py" deki bir işlev olduğunda olduğu gibi) y.py'den aradı.


32
2018-01-20 17:48





Python'u etkileşimli olarak çalıştırdığınızda __name__ değişkene bir değer atanır __main__. Benzer şekilde, bir Python modülünü komut satırından çalıştırdığınızda, başka bir modüle aktarmak yerine, __name__ özniteliğine değer atanır __main__modülün gerçek adı yerine. Bu şekilde, modüller kendi başlarına bakabilir __name__ Başka bir program için destek olarak veya komut satırından yürütülen ana uygulama olarak, nasıl kullanıldığını belirlemek için değer. Böylece, Python modüllerinde aşağıdaki deyim oldukça yaygındır:

if __name__ == '__main__':
    # Do something appropriate here, like calling a
    # main() function defined elsewhere in this module.
    main()
else:
    # Do nothing. This module has been imported by another
    # module that wants to make use of the functions,
    # classes and other useful bits it has defined.

30
2017-12-11 11:23