28 Soru: __Name__ == “__main__”: ne yapar?

tarafından oluşturulan soru Fri, May 25, 2018 12:00 AM

if __name__ == "__main__": ne yapar?

 
# 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))
    
5111
28 Yanıtlar                              28                         

Python yorumlayıcısı bir kaynak dosyayı okuduğunda, iki şey yapar:

  • __name__ gibi birkaç özel değişken ayarlar ve sonra

  • , dosyada bulunan tüm kodu çalıştırır.

Bunun nasıl çalıştığını ve Python komut dosyalarında her zaman gördüğümüz __name__ çeklerle ilgili sorunuzla nasıl ilgili olduğunu görelim.

Kod Örneği

İçe aktarma ve komut dosyalarının nasıl çalıştığını keşfetmek için biraz farklı bir kod örneği kullanalım. Aşağıdakilerin foo.py adlı bir dosyada olduğunu varsayalım.

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

Özel Değişkenler

Python yorumlayıcısı bir kaynak dosyayı okuduğunda, önce birkaç özel değişken tanımlar. Bu durumda, __name__ değişkenini önemsiyoruz.

Modülünüz Ana Program Olduğunda

Modülünüzü (kaynak dosya) ana program olarak kullanıyorsanız, ör.

 
python foo.py

tercüman "__main__" sabit kodlu dizeyi __name__ değişkenine atayacaktır, yani

 
# It's as if the interpreter inserts this at the top
# of your module when run as the main program.
__name__ = "__main__" 

Modülünüz Başka Birine İçe Aktarıldığında

Diğer taraftan, başka bir modülün ana program olduğunu ve modülünüzü içe aktardığını varsayalım. Bu, ana programda veya başka bir modülde ana programın ithalatında böyle bir ifade olduğunu gösterir:

 
# Suppose this is in some other main program.
import foo

Bu durumda, tercüman modülünüzün dosya adı foo.py'a bakacak, .py'u sıyırıp bu dizeyi modülünüzün __name__ değişkenine atayacak, yani

 
# It's as if the interpreter inserts this at the top
# of your module when it's imported from another module.
__name__ = "foo"

Modül Kodunu Çalıştırma

Özel değişkenler ayarlandıktan sonra, tercüman modüldeki tüm kodu her seferinde bir ifade olarak çalıştırır. Kod açıklamasıyla birlikte bir başka pencere daha açmak isteyebilirsiniz, böylece bu açıklamayı takip edebilirsiniz.

Her zaman

  1. "before import" dizesini yazdırır (tırnak işaretleri olmadan).

  2. math modülünü yükler ve math adlı bir değişkene atar. Bu, import math'u aşağıdakiyle değiştirmeye eşdeğerdir (__import__'un Python'da bir dize alan ve gerçek içe aktarmayı tetikleyen düşük düzeyli bir işlev olduğunu unutmayın):

 
# Find and load a module given its string name, "math",
# then assign it to a local variable called math.
math = __import__("math")
  1. "before functionA" dizesini yazdırır.

  2. def bloğunu yürütür, bir işlev nesnesi oluşturur, sonra bu işlev nesnesini functionA adlı bir değişkene atar.

  3. "before functionB" dizesini yazdırır.

  4. İkinci bir def bloğunu yürütür, başka bir işlev nesnesi oluşturur ve ardından functionB adlı bir değişkene atar.

  5. "before __name__ guard" dizesini yazdırır.

Yalnızca Modülünüz Ana Program Olduğunda

  1. Modülünüz ana programsa, __name__'un gerçekten "__main__" olarak ayarlandığını ve bu iki işlevi çağırdığını, "Function A" ve "Function B 10.0" dizelerini yazdırdığını görecektir.

Yalnızca Modülünüz Başka Birinden İçe Aktarıldığında

  1. ( yerine ) Modülünüz ana program değilse ancak başka bir program tarafından alınmışsa, __name__, "foo" olur, "__main__" olur ve if ifadesinin gövdesini atlar.

Her zaman

  1. Her iki durumda da "after __name__ guard" dizesini basacaktır.

Özet

Özet olarak, işte iki durumda ne basılacağı:

 
# 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

Neden Bu Şekilde Çalışıyor?

Doğal olarak neden birisinin bunu isteyeceğini merak edebilirsiniz. Bazen, diğer programlar ve /veya modüller tarafından bir modül olarak kullanılabilen ve aynı zamanda ana programın kendisi olarak da çalıştırılabilen .py bir dosya yazmak istersiniz. Örnekler:

  • Modülünüz bir kütüphanedir, ancak bazı birim testlerini veya bir demosu çalıştığı bir komut dosyası moduna sahip olmak istersiniz.

  • Modülünüz yalnızca ana program olarak kullanılır, ancak bazı birim testlerine sahiptir ve test çerçevesi, betiğiniz gibi .py dosyayı içe aktarıp özel test işlevleri çalıştırarak çalışır. Sadece modülü içe aktardığı için betiği çalıştırmayı denemek istemezsiniz.

  • Modülünüz çoğunlukla ana program olarak kullanılır, ancak aynı zamanda ileri düzey kullanıcılar için programcı dostu bir API sağlar.

Bu örneklerin ötesinde, Python'da bir komut dosyası çalıştırmanın sadece birkaç sihirli değişken ayarlaması çok zarif.s ve betiği içe aktarma. Komut dosyasını "Çalıştırmak", komut dosyasının modülünü içe aktarmanın bir yan etkisidir.

Düşünce İçin Yiyecek

  • Soru: Birden fazla __name__ kontrol bloğunu alabilir miyim? Cevap: Bunu yapmak garip, ancak dil sizi durduramayacak.

  • Aşağıdakilerin foo2.py'da olduğunu varsayalım. Komut satırında python foo2.py derseniz ne olur? Neden?

 
# 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")
  • Şimdi, __name__'daki foo3.py çekini kaldırırsanız ne olacağını anlayın:
 
# 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")
  • Bir komut dosyası olarak kullanıldığında bu ne işe yarar? Modül olarak içe aktarıldığında?
 
# Suppose this is in foo4.py
__name__ = "__main__"

def bar():
    print("bar")

print("before __name__ guard")
if __name__ == "__main__":
    bar()
print("after __name__ guard")
    
5471
2019-06-24 03: 21: 09Z
  1. Meraktan: Bir python betiğinde subprocess.run('foo_bar.py') kullanıyorsam ne olur? Sanırım foo_bar'un __name__ = '__main__' ile, tıpkı el ile foo_bar.py cm ipucu verdiğimde olduğu gibi başlayacağını düşünüyorum. Bu böyle mi? @MrFooz 'cevabını hesaba katarak, bunu yaparken ve istediğim kadar çok "ana" modüle sahip olmakta hiçbir problem olmamalı. __name__ değerini değiştirmek veya birbirinden bağımsız olarak birkaç tane oluşturmak bile, (ya da subprocess ile birbirini oluşturan örnekler) birbirleriyle etkileşime girerek Python için her zamanki gibi iş yapmalıdır. Bir şey mi özledim?
    2019-02-18 16: 09: 14Z
  2. @ hajef İşlerin subprocess.run ile nasıl çalışacağı konusunda haklısınız. Bununla birlikte, genellikle komut dosyaları arasında kod paylaşmanın daha iyi bir yolu, modüller oluşturmak ve komut dosyalarının birbirlerini komut dosyası olarak çağırmak yerine ortak modülleri çağırmasını sağlamaktır. Çoğu hata ayıklayıcının işlem sınırlarını aşmadığı için subprocess.run çağrılarda hata ayıklamak zordur, ek işlemler oluşturup yok etmek için önemsiz olmayan bir sistem ek yükü ekleyebilir, vb.
    2019-02-19 16: 16: 03Z
  3. Gıda için foo2.py örneğindeki düşünceye yönelik bir şüphem var. foo2.py import functionB ne yapar? Benim görüşüme göre foo2.py dosyasını functionB
    'den içe aktarıyor
    2019-02-24 13: 47: 03Z
  4. @ MrFooz Asla böyle bir şey yapmak istemedim xD Sadece aklıma geldi ve muhtemelen ppl'ye yardım etmenin garip olduğunu anladım. aklını bu tür şeylerin etrafına sarmak. @ user471651 Neden from foo2 import functionB foo2'yi functionB'dan içe aktarmalı? Bu anlamsal bir çarpıtma. from module import method, yöntemi modülden içe aktarır.
    2019-02-25 15: 51: 16Z
  5. bir python tanrısı mısınız? güzel açıklama: D
    2019-06-18 03: 20: 56Z

Komut dosyanız Python yorumlayıcısına komut olarak geçirerek çalıştırıldığında,

 
python myscript.py

Girinti seviyesi 0 olan tüm kod çalıştırılır. Tanımlanan fonksiyonlar ve sınıflar tanımlanmıştır, ama tanımlanmış fakat kodlarından hiçbiri çalıştırılmaz. Diğer dillerden farklı olarak, otomatik olarak çalışan main() işlevi yoktur - main() işlevi örtülü olarak en üst düzeydeki tüm kodlardır.

Bu durumda, üst seviye kod if bloğudur. __name__, geçerli modülün adını değerlendiren yerleşik bir değişkendir. Bununla birlikte, bir modül doğrudan çalıştırılıyorsa (yukarıdaki myscript.py'daki gibi), __name__ yerine "__main__" dizisine ayarlanır. Böylece, komut dosyanızın doğrudan çalıştırılıp çalıştırılmadığını veya test ederek başka bir şey tarafından içe aktarıldığını test edebilirsiniz

 
if __name__ == "__main__":
    ...

Komut dosyanız başka bir modüle içe aktarılıyorsa, çeşitli işlevi ve sınıf tanımları içe aktarılacak ve üst düzey kodu çalıştırılacak, ancak yukarıdaki if yan tümcesinin kodundaki kod çalıştırılmayacak koşul karşılanmadığı için. Temel bir örnek olarak, aşağıdaki iki komut dosyasını 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ı şu şekilde çağırdıysanız

 
python one.py

Çıktı olacak

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

Bunun yerine two.py kullanıyorsanız:

 
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, one modülü yüklendiğinde, __name__, "one" yerine "__main__"'a eşittir.

    
1640
2018-01-31 13: 28: 16Z

__name__ değişkeni (imho) için en basit açıklama şudur:

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ırmanız size şu sonucu verecektir:

 
$ python a.py
Hello World from b!

Gördüğünüz gibi, bir modül alındığında, Python bu modülde globals()['__name__']'u modül adına ayarlıyor. Ayrıca, içeri aktardıktan sonra modüldeki tüm kodlar çalıştırılmaktadır. if ifadesi False olarak değerlendirildiğinden, bu bölüm yürütülmemektedir.

 
$ 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 bu dosyadaki globals()['__name__']'u "__main__" olarak ayarlar. Bu sefer if deyimi True olarak değerlendiriliyor ve çalışıyor.

    
653
2018-12-18 09: 25: 19Z
  

if __name__ == "__main__": ne yapar?

Temel bilgileri ana hatlarıyla belirtmek için:

  • Programınıza giriş noktası olan modüldeki __name__ genel değişkeni '__main__''dur. Aksi takdirde, modülü modüle göre içe aktardığınız addır.

  • Öyleyse, if bloğunun altındaki kod yalnızca modül programınıza giriş noktasıysa çalışır.

  • Modül içindeki kodun içe aktarma altındaki kod bloğunu çalıştırmadan diğer modüller tarafından alınabilmesini sağlar.


Neden buna ihtiyacımız var?

Kodunuzu Geliştirme ve Test Etme

Modül olarak kullanılmak üzere tasarlanmış bir Python betiği yazdığınızı söyleyin:

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

Siz bu işlev çağrısı en altına ekleyerek modülü test edebilirsiniz:

 
do_important()

ve onu (komut isteminde) aşağıdaki gibi bir şeyle çalıştırma:

 
~$ python important.py

Sorun

Ancak, modülü başka bir komut dosyasına içe aktarmak istiyorsanız:

 
import important

İçe aktarırken, do_important işlevi çağrılır, bu nedenle en alt kısımda do_important() numaralı işlev çağrınızı yorumlayabilirsiniz.

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

Ve sonra test işlev çağrınızı yorumlayıp yorumlamadığınızı hatırlamanız gerekir. Ve bu ekstra karmaşıklık, geliştirme sürecinizi daha zahmetli hale getirerek unutabileceğiniz anlamına gelir.

Daha İyi Bir Yol

__name__ değişkeni, Python yorumlayıcısının şu anda olduğu yerde ad alanını işaret eder.

Alınan bir modülün içinde, o modülün adı.

Ancak birincil modülün içinde (veya etkileşimli bir Python oturumu, yani tercümanın Oku, Değerlendir, Yazdır Döngü veya REPL) "__main__"’undan itibaren her şeyi çalıştırıyorsunuz.

Yani yürütmeden önce kontrol ederseniz:

 
if __name__ == "__main__":
    do_important()

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

Daha İyi Bir Yol

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

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

Kodu koyarsak, böyle bir fonksiyonda geliştikçe ve test ederken egzersiz yapmak istiyoruz ve hemen sonra '__main__' için kontrolümüzü yapıyoruz:

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

Artık modülü birincil modül olarak çalıştırırsak çalışacak olan modülümüzün sonu için son bir işleve sahibiz.

main işlevini çalıştırmadan modülün ve işlevlerinin ve sınıflarının diğer komut dosyalarına alınmasına izin verecek ve ayrıca farklı bir '__main__' modülünden çalışırken modülün (ve işlevlerinin ve sınıflarının) çağrılmasına izin verecek

 
import important
important.main()

Bu deyim, Python belgelerinde __main__ modülünün bir açıklamasında da bulunabilir. Bu metin belirtir:

  

Bu modül, içinde bulunduğu (aksi takdirde isimsiz) kapsamı gösterir.   tercümanın ana programı yürütülür.   Standart girdi, bir komut dosyasından veya etkileşimli bir komut isteminden. O   deyimsel “koşullu senaryo” stanza'nın bulunduğu ortamdır.   bir komut dosyasının çalışmasına neden olur:

 
if __name__ == '__main__':
    main()
    
470
2018-03-27 02: 27: 47Z

if __name__ == "__main__", komut dosyası python myscript.py gibi bir komut kullanarak komut satırından çalıştırıldığında (örneğin) çalışan bölümdür.

    
110
2015-07-10 15: 49: 13Z
  

if __name__ == "__main__": ne yapar?

__name__ genel bir değişkendir (Python'da, global aslında modül düzeyinde anlamına gelir) Tüm ad alanlarında. Tipik olarak modülün adıdır (str türü olarak).

Ancak, tek özel durum olarak, hangi kodda Python işleminde olursanız olun, mycode.py'da olduğu gibi:

 
python mycode.py

aksi takdirde adsız genel ad alanı '__main__''a __name__'a atanır.

Böylece, son satırlar

dahil  
if __name__ == '__main__':
    main()
  • mycode.py betiğinizin sonunda,
  • bir Python işlemi tarafından çalıştırılan birincil, giriş noktası modülü olduğunda,

, komut dosyanızın benzersiz bir şekilde tanımlanmış main işlevinin çalışmasına neden olur.

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

 
import mycode
# ... any amount of other code
mycode.main()
    
71
2017-01-10 17: 35: 04Z

Burada söz konusu kodun mekaniği olan “Nasıl” ile ilgili birçok farklı yaklaşım var, ancak benim için “Neden” i anlamadan hiçbiri anlam ifade etmedi. Bu, özellikle yeni programcılar için faydalı olmalıdır.

"ab.py" dosyasını alın:

 
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?

xy.py'u yürüttüğünüzde, import ab. İmport ifadesi modülü hemen içe aktarma sırasında çalıştırır, böylece ab'un kalanı, xy'un kalanından önce yürütülür. ab ile bittiğinde, xy ile devam ediyor.

Tercüman, hangi komut dosyalarının __name__ ile çalıştığını takip eder. Bir komut dosyası çalıştırdığınızda - neyi adlandırdığınız önemli değil - tercüman, "__main__"'u çağırır, harici bir komut dosyasını çalıştırdıktan sonra döndürülen ana veya 'ana sayfa' komut dosyası yapar.

Bu "__main__" komut dosyasından çağrılan başka bir komut dosyasının adı __name__ olarak adlandırılır (örneğin, __name__ == "ab.py"). Bu nedenle, if __name__ == "__main__": satırı, ilk olarak yürütülen 'home' komut dosyasını mı yorumlayıp ayrıştırdığını veya geçici olarak başka bir (harici) komut dosyasına göz atıp atmadığını belirlemek için tercümanın testidir. Bu, programcıya doğrudan harici olarak çağrılırsa komut dosyasının farklı davranmasını sağlama esnekliği sağlar.

Neler olduğunu anlamak için ilk önce girintisiz satırlara ve komut dosyalarında göründüğü sıralamaya odaklanarak yukarıdaki kodu inceleyelim. Bu fonksiyonu - veya def - bloklar çağrılana kadar kendi başlarına hiçbir şey yapmazlar. Tercüman kendi kendine mırıldanırsa ne söyleyebilir:

  • xy.py dosyasını 'home' dosyası olarak açın; "__main__" değişkeninde __name__ olarak adlandırın.
  • __name__ == "ab.py" ile dosyayı içe aktarın ve açın.
  • Ah, bir işlev. Bunu hatırlayacağım.
  • Tamam, işlev a(); Bunu daha yeni öğrendim. ' ab dosyasındaki bir işlev '.
  • yazdırılıyor
  • Dosyanın sonu; "__main__"'a dön!
  • Ah, bir işlev. Bunu hatırlayacağım.
  • Başka bir.
  • İşlev x(); tamam, ' çevresel görev: diğer projelerde faydalı olabilir '.
  • Bu nedir? if deyimi. Pekala, koşul yerine getirildi (__name__ değişkeni "__main__" olarak ayarlandı), bu yüzden main() işlevine gireceğim ve ' ana işlevi yazdırıyorum: eylemin olduğu yer burası '.

Alttaki iki satır şu anlama gelir: "Bu, "__main__" veya" home "komut dosyasıysa, main() adlı işlevi yürütünüz". Bu yüzden betiğin işlevselliğinin ana akışını içeren bir def main(): blok yukarı göreceksiniz.

  

Neden bunu uyguladın?

İçe aktarma ifadeleri hakkında daha önce söylediklerimi hatırlıyor musunuz? Bir modülü içe aktardığınızda, sadece onu 'tanımaz' ve daha fazla talimat beklemez - aslında betiğin içindeki tüm çalıştırılabilir işlemleri çalıştırır. Böylece, betiğinizin etini main() işlevine koymak, onu başka bir komut dosyası tarafından içe aktarıldığında derhal çalıştırılmayacak şekilde yalıtmak için etkin bir şekilde karantinaya alır.

Yine, istisnalar olacak, ancak yaygın uygulama main()'un genellikle harici olarak çağrılmamasıdır. Öyleyse bir şeyi daha merak ediyor olabilirsiniz: main()'u aramıyorsak, neden senaryoyu biruzun boylu? Bunun nedeni birçok kişinin komut dosyalarını, dosyadaki kodun geri kalanından bağımsız olarak çalıştırılmak üzere oluşturulan bağımsız işlevlerle yapılandırmasıdır. Daha sonra betiğin gövdesinde başka bir yere çağırılırlar. Bu beni buna getiriyor:

  

Ancak kod onsuz çalışır

Evet, doğru. Bu ayrı işlevler, main() işlevinde bulunmayan bir satır içi komut dosyasından çağrılabilir . Alışmışsanız (benim gibi, programlamadaki ilk öğrenim aşamalarımda) tam olarak ihtiyacınız olanı yapan satır içi komut dosyaları oluşturmaya alıştınız ve tekrar bu işleme ihtiyacınız olursa tekrar çözmeye çalışacaksınız. kodunuzda bu tür bir iç yapıya alışık değilsiniz, çünkü inşa etmek daha karmaşık ve okumak için sezgisel değil.

Ama bu muhtemelen harici olarak adlandırılan işlevlerine sahip olamayacak bir betiktir, çünkü eğer öyleyse hemen derhal değişkenleri hesaplamaya ve atamaya başlayacaktır. Ve bir işlevi yeniden kullanmaya çalışıyorsanız, yeni komut dosyanızın eskisiyle çelişen değişkenlerin olacağı kadar yakından ilişkili olması olasıdır.

Bağımsız işlevleri ayırırken, önceki çalışmanızı başka bir komut dosyasına çağırarak yeniden kullanma yeteneği kazanırsınız. Örneğin, "example.py" "xy.py" dosyasını içe aktarabilir ve "xy" işlevini kullanarak "xy.py" den x()'u çağırabilir. (Belki belirli bir metin dizesinin üçüncü sözcüğünü büyük harf kullanmaktadır; bir sayı listesinden bir NumPy dizisi oluşturmak ve bunları kareye almak veya bir 3D yüzeyini azaltmak. Olasılıklar sınırsızdır.)

(Bir kenara, bu soruyu yanıtlayan @kindall tarafından verilen cevap anlamama yardım etti - neden, nasıl değil, ne yazık ki 'in bir kopyası olarak işaretlendi bu bir , sanırım bir hata.)

    
62
2018-05-23 22: 29: 32Z

Modülümüzde (M.py) belirli ifadeler olduğunda, ana olarak çalışacakken (içe aktarılmadığında) yürütülmesini istiyoruz, bu ifadeleri (test durumları, baskı ifadeleri) bu if bloğunun altına yerleştirebiliriz.

Varsayılan olarak (modül ana olarak çalıştığında, içe aktarılmadığında) __name__ değişkeni "__main__" olarak ayarlanır ve içe aktarıldığında __name__ değişkeni farklı bir değer alır, büyük olasılıkla modülün adı ('M') . Bu, modüllerin farklı türevlerini birlikte çalıştırmada ve belirli girişlerini ayırmada yardımcı olur. çıktı ifadeleri ve ayrıca herhangi bir test durumu varsa.

Kısaca , modül içe aktarılırken kodun çalışmasını önlemek için bu 'if __name__ == "main"' bloğunu kullanın.

    
45
2018-05-23 22: 07: 29Z

Cevabı daha soyut bir şekilde inceleyelim:

Bu kodu x.py içerisinde aldığımızı varsayalım:

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

"x.py" komutunu çalıştırdığımızda A ve B blokları çalıştırıldı.

Ama başka bir modül çalıştırırken sadece A bloğu (B değil) çalıştırılır, örneğin xy'nin içe aktarıldığı ve kodun oradan çalıştırıldığı "x." gibi bir fonksiyon çalıştırılır. py "y.py den çağrılır).

    
35
2015-03-04 20: 31: 20Z

Basitçe söylemek gerekirse, __name__, betiğin ana modül olarak mı yoksa içe aktarılmış bir modül olarak mı çalıştırıldığını tanımlayan her komut dosyası için tanımlanmış bir değişkendir.

Öyleyse iki senaryomuz varsa;

 
#script1.py
print "Script 1's name: {}".format(__name__)

ve

 
#script2.py
import script1
print "Script 2's name: {}".format(__name__)

Komut1'i çalıştırmanın çıktısı

 
Script 1's name: __main__

Ve script2'yi çalıştırmanın çıktısı:

 
Script1's name is script1
Script 2's name: __main__

Gördüğünüz gibi, __name__ bize hangi kodun 'ana' modül olduğunu söyler. Bu harika, çünkü sadece kod yazabilir ve C /C ++ gibi yapısal konular hakkında endişelenmenize gerek kalmaz, eğer bir dosya 'main' işlevini uygulamazsa, çalıştırılabilir olarak derlenemez ve eğer o zaman kütüphane olarak kullanılamaz.

Harika bir şey yapan bir Python betiği yazdığınızı veBaşka amaçlar için yararlı olan bir tekne yükü işlevi gerçekleştirirsiniz. Eğer onları kullanmak istersem sadece betiğinizi alabilir ve programınızı çalıştırmadan kullanabilirim (kodunuzun sadece if __name__ == "__main__": bağlamında çalıştırıldığı düşünülürse). Oysa C /C ++ 'da, bu parçaları daha sonra dosyayı içeren ayrı bir modüle bölmek zorunda kalacaksınız. Aşağıdaki durumu hayal edin;

 C’de karışık ithalat

Oklar içe aktarma bağlantılarıdır. Her biri önceki modül kodunu eklemeye çalışan üç modül için altı dosya (dokuz, uygulama dosyalarını sayarak) ve beş bağlantı bulunur. Bu, özellikle bir kütüphane olarak derlenmedikçe, bir C projesine başka bir kod eklemeyi zorlaştırır. Şimdi Python için hayal edin:

 Python'da zarif içe aktarma

Bir modül yazarsınız ve eğer birisi kodunuzu kullanmak isterse, onu yalnızca içe aktarır ve __name__ değişkeni, programın çalıştırılabilir bölümünü kitaplık bölümünden ayırmaya yardımcı olabilir.

    
35
2018-05-23 22: 28: 19Z
  1. C /C ++ resmi yanlıştır: aynı birim adının 3 katı ( dosya1 ).
    2018-01-11 12: 59: 53Z

Python'u etkileşimli olarak çalıştırdığınızda, yerel __name__ değişkenine __main__ değeri atanır. Benzer şekilde, bir Python modülünü komut satırından başka bir modüle aktarmak yerine, çalıştırdığınızda, __name__ özelliğine modülün asıl adı yerine __main__ değeri atanır. Bu şekilde, modüller kendilerinin nasıl kullanıldığını belirlemek için kendi __name__ değerlerine bakabilir, ister başka bir programa destek olsun, ister komut satırından yürütülen ana uygulama olarak bakabilirler. Bu nedenle, aşağıdaki deyim Python modüllerinde 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.
    
32
2013-12-11 11: 23: 53Z

düşünün:

 
if __name__ == "__main__":
    main()

Python betiğinin __name__ özniteliğinin "__main__" olup olmadığını denetler. Başka bir deyişle, programın kendisi yürütülürse, öznitelik __main__ olur, bu nedenle program yürütülür (bu durumda main() işlevi).

Ancak, Python betiğiniz bir modül tarafından kullanılıyorsa, if ifadesinin dışındaki herhangi bir kod çalıştırılır, bu nedenle if \__name__ == "\__main__" yalnızca programın modül olarak kullanılıp kullanılmadığını kontrol etmek için kullanılır ve bu nedenle çalışıp çalışmayacağına karar verir. kod.

    
29
2018-05-23 22: 31: 42Z

if __name__ == '__main__' ile ilgili herhangi bir açıklama yapmadan önce, __name__'un ne olduğunu ve ne yaptığını anlamak önemlidir.

  

__name__ Nedir?

__name__ bir DunderAlias ​​ 'dır - genel bir değişken olarak düşünülebilir (modüllerden erişilebilir) ve global ile benzer şekilde çalışır.

type(__name__) (<class 'str'> veren) ile gösterilen bir dizedir (yukarıda bahsedildiği gibi global) ve her ikisi için de Python 3 ve Python 2 sürümleri.

  

Nerede:

Yalnızca komut dosyalarında kullanılamaz, ayrıca yorumlayıcıda ve modüllerde /paketlerde de bulunabilir.

Tercüman:

 
>>> print(__name__)
__main__
>>>

Senaryo:

test_file.py :

 
print(__name__)

__main__’da sonuçlanıyor

Modül veya paket:

somefile.py:

 
def somefunction():
    print(__name__)

TEST_file.py:

 
import somefile
somefile.somefunction()

somefile’da sonuçlanıyor

Bir paket veya modülde kullanıldığında, __name__'un dosyanın adını aldığına dikkat edin. Gerçek modülün veya paket yolunun yolu belirtilmemiş, ancak buna izin veren kendi DunderAlias ​​__file__'a sahip.

Görmelisiniz ki, ana dosyanın (veya programın) nerede __name__, nerede her zaman olacaktır? __main__, ve eğer bir modül /paket ise veya başka bir şeyden kaçıyorsa Python betiği, nereden geldiği dosyanın adını döndürür.

  

Uygulama:

Değişken olmak, değerinin üzerine yazılabileceği anlamına gelir , üzerine yazılabilir ("olabilir" anlamına gelmez "), __name__ değerinin üzerine yazmak, okunabilirliğin olmamasına neden olur. Öyleyse, bir nedenden dolayı yapmayın. Bir değişkene ihtiyacınız varsa, yeni bir değişken tanımlayın.

Her zaman __name__ değerinin __main__ veya dosya adı olduğu varsayılır. Bir kez daha bu varsayılan değerin değiştirilmesi, daha iyi sonuçlara yol açabileceğinden daha fazla kargaşaya yol açacak, hatta daha fazla soruna yol açacaktır.

örnek:

 
>>> __name__ = 'Horrify' # Change default from __main__
>>> if __name__ == 'Horrify': print(__name__)
...
>>> else: print('Not Horrify')
...
Horrify
>>>

Genel olarak if __name__ == '__main__'’u komut dosyalarına eklemeniz iyi bir uygulamadır.

  

Şimdi if __name__ == '__main__'’a cevap vermek için:

Artık __name__ işin davranışının daha netleştiğini biliyoruz:

Bir if , aşağıdakileri içeren bir akış kontrolü ifadesidir Verilen değer doğruysa kod bloğu çalıştırılır. __name__'un da alabileceğini gördük.  __main__ veya alındığı dosya adı.

Bu, __name__, __main__'a eşitse, dosyanın ana dosya olması ve komut dosyasına içe aktarılan bir modül veya paket değil, gerçekten çalışıyor olması (veya yorumlayıcı) olması gerektiği anlamına gelir.

Eğer gerçekten __name__, __main__ değerini alırsa, o zaman bu kod bloğunda ne olursa olsun yürütülür.

Bu, çalışan dosya ana dosyaysa (veya doğrudan tercümandan çalışıyorsanız) o koşulun yürütülmesi gerektiğini söyler. Eğer bir paketse o zaman yapmamalı ve değer __main__ olmayacak.

  

Modüller:

__name__, modül adını tanımlamak için modüllerde de kullanılabilir

  

Çeşitlemeler:

Ayrıca burada göstereceğim __name__ ile diğer, daha az yaygın ancak yararlı şeyler yapmak da mümkündür:

Yalnızca dosya bir modül veya paketse çalıştırma:

 
if __name__ != '__main__':
    # Do some useful things 

Dosya ana ise bir koşulu çalıştırıyorsa, değilse ana koşulu:

 
if __name__ == '__main__':
    # Execute something
else:
    # Do some useful things

Ayrıca, kütüphaneleri ayrıntılı bir şekilde kullanmadan paketler ve modüller üzerinde çalıştırılabilir yardım işlevleri /yardımcı programları sağlamak için de kullanabilirsiniz.

Ayrıca, modüllerin komut satırından ana komut dosyaları olarak çalıştırılmasını da sağlar, bu da çok yararlı olabilir.

    
25
2018-05-23 22: 39: 09Z

Cevabı derinlemesine ve basit kelimelerle kırmanın en iyisi olduğunu düşünüyorum:

__name__: Python'daki her modül __name__ adında özel bir özelliğe sahiptir. Modülün ismini döndüren yerleşik bir değişkendir.

__main__: Diğer programlama dilleri gibi Python'da da yürütme giriş noktası vardır, yani ana. '__main__' , üst düzey kodun yürütüldüğü kapsamın adıdır . Temel olarak bir Python modülünü kullanmanın iki yolu vardır: Doğrudan komut dosyası olarak çalıştırın veya içe aktarın. Bir modül komut dosyası olarak çalıştırıldığında, __name__, __main__ olarak ayarlanır.

Böylece, modül ana program olarak çalıştırıldığında, __name__ özelliğinin değeri __main__ olarak ayarlanır. Aksi halde, __name__'un değeri modülün adını içerecek şekilde ayarlanır.

    
22
2018-05-23 22: 30: 36Z

Bir Python dosyasının komut satırından çağrılması için özel bir işlemdir. Bu genellikle "main ()" işlevini çağırmak veya örneğin komut satırı argümanları gibi diğer uygun başlangıç ​​kodlarını çalıştırmak için kullanılır.

Birkaç şekilde yazılabilir. Başka bir:

 
def some_function_for_instance_main():
    dosomething()


__name__ == '__main__' and some_function_for_instance_main()

Bunu üretim kodunda kullanmanız gerektiğini söylemiyorum, ancak if __name__ == '__main__' hakkında "sihirli" bir şey olmadığını göstermek için hizmet ediyor. Bir ana f çağırmak için iyi bir kongredirPython dosyalarında unction.

    
20
2018-09-03 07: 05: 11Z
  1. Bu kötü formu 1) yan etkilere ve 2) and suistimale güvendiğiniz için kabul ediyorum. and, iki boolean ifadenin her ikisinin de doğru olup olmadığını kontrol etmek için kullanılır. and'un sonucuyla ilgilenmediğiniz için, bir if ifadesi niyetlerinizi daha açık şekilde bildirir.
    2013-12-26 18: 07: 26Z
  2. Boolean operatörlerinin kısa devre davranışının bir akış kontrol mekanizması olarak kullanılmasının kötü bir tarz olup olmadığı sorusunu bir kenara bırakmak, en büyük sorunun şudur ki soruyu hiç yanıtlamıyor .
    2015-07-10 15: 33: 06Z

Sistemin (Python yorumlayıcısı) kaynak dosyalar (modüller) için sağladığı birkaç değişken vardır. Değerlerini istediğiniz zaman alabilirsiniz, bu yüzden __name__ değişkenine /niteliğine odaklanalım:

Python bir kaynak kod dosyası yüklediğinde, içinde bulunan tüm kodu çalıştırır. (Dosyada tanımlanan tüm yöntem ve işlevleri aramadığını, ancak bunları tanımladığını unutmayın.)

Tercüman, kaynak kod dosyasını yürütmeden önce, o dosya için birkaç özel değişken tanımlar; __name__ , Python'un her kaynak kod dosyası için otomatik olarak tanımladığı özel değişkenlerden biridir.

Python bu kaynak kod dosyasını ana program olarak yüklüyorsa (yani çalıştırdığınız dosya), o zaman bu dosyanın "__main__" değerine sahip olması için özel __name__ değişkenini ayarlar. .

Bu başka bir modülden içe aktarılıyorsa, o modülün adına __name__ ayarlanacaktır.

Öyleyse, örneğinizdeki kısımda:

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

, kod bloğu anlamına gelir:

 
lock = thread.allocate_lock()
thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))

sadece modülü doğrudan çalıştırdığınızda çalıştırılır; başka bir modül çağırıyor /içeri alıyorsa kod bloğu çalışmayacak çünkü __name__ değeri bu belirli durumda " ana " değerine eşit olmayacak.

Bunun yardımcı olacağını umarım.

    
19
2016-07-20 09: 30: 24Z

if __name__ == "__main__": temel olarak en üst düzey komut dosyası ortamıdır ve tercümanı belirtir ('İlk önce yürütülecek en yüksek önceliğe sahibim').

'__main__', üst düzey kodun yürütüldüğü kapsamın adıdır. Bir modülün __name__'u standart girdiden, bir komut dosyasından veya etkileşimli bir istemden okunduğunda '__main__''a eşit olarak ayarlanır.

 
if __name__ == "__main__":
    # Execute only if run as a script
    main()
    
16
2018-05-23 22: 14: 07Z

Bunun nedeni

 
if __name__ == "__main__":
    main()

öncelikle alma kilidini engellemekten kaçınmak içindir > kodun doğrudan içe aktarılmasından kaynaklanan sorunlar. Dosyanızın doğrudan çağrılması durumunda main()'un çalıştırılmasını istiyorsunuz (bu __name__ == "__main__" davasıdır), ancak kodunuz içe aktarılmışsa içe aktarma kilitleme sorunlarından kaçınmak için ithalatçının kodunuzu gerçek ana modülden girmesi gerekir.

Yan etkisi, birden çok giriş noktasını destekleyen bir metodolojide otomatik olarak oturum açmanızdır. Programınızı, giriş noktası olarak main() kullanarak çalıştırabilirsiniz, ancak yapmanız gerekmez . setup.py, main()'u beklerken, diğer araçlar alternatif giriş noktaları kullanır. Örneğin, dosyanızı gunicorn işlemi olarak çalıştırmak için, app() yerine main() işlevini tanımlarsınız. setup.py'da olduğu gibi, gunicorn da kodunuzu alır;     

14
2018-04-18 21: 05: 59Z
  1. Alma Kilidi hakkında bilgi edinmek iyi. Lütfen [...] biraz daha fazlasını bölümlendiren bir metodolojide oturum açabilir misiniz?
    2018-01-11 13: 06: 38Z
  2. @ Wolf: Tabii. Çoklu giriş noktası metodolojisi hakkında birkaç cümle ekledim.
    2018-04-14 00: 26: 20Z

Bu sayfadaki cevaplar boyunca çok fazla okudum. Bir şeyi biliyorsanız, kesinlikle bu cevapları anlayacağınızı, aksi halde hala kafanızın karışık olduğunu söyleyebilirim.

Kısa olmak için birkaç nokta bilmeniz gerekir:

  1. import a eylemi aslında "a" ile çalıştırılabilecek her şeyi çalıştırır

  2. 1. nokta nedeniyle, içe aktarırken her şeyin "a" da çalıştırılmasını istemeyebilirsiniz

  3. 2. noktadaki sorunu çözmek için python bir durum kontrolü koymanıza izin verir

  4. __name__, tüm .py modüllerinde örtük bir değişkendir; a.py alındığında, a.py modülünün __name__ değeri "a" dosya adına ayarlanır; a.py doğrudan "python a.py" kullanılarak çalıştırıldığında, a.py giriş noktası demektir, a.py modülünün __name__ değeri __main__ dizesine ayarlanır

  5. Python'un her modül için __name__ değişkenini nasıl ayarladığı mekanizmasına bağlı olarak 3. noktaya nasıl ulaşılacağını biliyor musunuz? Cevap oldukça kolay, değil mi? Bir if koşulu koyun: if __name__ == "__main__": ...; __name__ == "a"'u fonksiyonel ihtiyacınıza bağlı olarak bile ekleyebilirsiniz.

Python'un özel olduğu önemli nokta 4'tür! Gerisi sadece temel bir mantıktır.

    
13
2018-06-24 15: 48: 36Z
  1. Evet, 1. nokta anlamak için çok önemlidir. Bundan sonra, bu mekanizmaya olan ihtiyaç açıkça ortaya çıkıyor.
    2019-03-24 21: 16: 18Z

düşünün:

 
print __name__

Yukarıdakilerin çıktısı __main__’dur.

 
if __name__ == "__main__":
  print "direct method"

Yukarıdaki ifade doğrudur ve "direct method" 'i yazdırır. Bu sınıfı başka bir sınıfa içe aktardılarsa, "direct method" 'ı yazdırmadığını, çünkü içe aktarırken __name__ equal to "first model name" ayarlayacağını varsayalım.

    
13
2019-02-06 23: 16: 06Z
  

Dosyayı bir komut dosyası kadar bir içe aktarılabilir modül olarak da kullanılabilir hale getirebilirsiniz.

fibo.py (fibo adlı bir modül)

 
# Other modules can IMPORT this MODULE to use the function fib
def fib(n):    # write Fibonacci series up to n
    a, b = 0, 1
    while b < n:
        print(b, end=' ')
        a, b = b, a+b
    print()

# This allows the file to be used as a SCRIPT
if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

Referans: https://docs.python.org/3.5/tutorial/modules. html

    
12
2017-03-13 21: 44: 26Z

Bu cevap Python'u öğrenen Java programcıları içindir. Her Java dosyası genellikle bir ortak sınıf içerir. Bu sınıfı iki şekilde kullanabilirsiniz:

  1. Sınıfı diğer dosyalardan arayın. Çağıran programa aktarmanız yeterlidir.

  2. Sınama amacıyla sınıfı tek başına çalıştırın.

İkinci durumda, sınıf, public static void main () yöntemini içermelidir. Python'da bu amaç global olarak tanımlanmış '__main__' etiketi ile sunulmaktadır.

    
8
2018-10-18 03: 09: 32Z

Bu .py dosyası diğer .py dosyaları tarafından içe aktarılırsa, "i altındaki kodf ifadesi "yürütülmeyecek.

Bu .py kabuk altında python this_py.py tarafından çalıştırılırsa veya Windows'ta çift tıklatıldıysa. "if ifadesi" altındaki kod çalıştırılacak.

Genellikle test için yazılır.

    
5
2018-06-19 11: 44: 29Z

Bir dosya oluşturun, a.py :

 
print(__name__) # It will print out __main__

__name__, bu dosya doğrudan çalıştırıldığında , bunun ana dosya olduğunu gösteren her zaman __main__’a eşittir.

Aynı dizinde, b.py , başka bir dosya oluşturun:

 
import a  # Prints a

Çalıştır. a , yani içe aktarılan dosyanın adını basacaktır.

Dolayısıyla, aynı dosyanın iki farklı davranışını göstermek için, bu yaygın olarak kullanılan bir numaradır:

 
# Code to be run when imported into another python file

if __name__ == '__main__':
    # Code to be run only when run directly
    
4
2018-05-23 22: 34: 14Z

eğer ad == ' ana ':

__name__ == '__main__':'un oldukça sık olup olmadığını görüyoruz.

Bir modülün içe aktarılıp aktarılmadığını kontrol eder.

Başka bir deyişle, if bloğundaki kod yalnızca kod doğrudan çalıştığında çalıştırılır. Burada directly, not imported anlamına gelir.

Modülün adını basan basit bir kod kullanarak ne yaptığını görelim:

 
# test.py
def test():
   print('test module name=%s' %(__name__))

if __name__ == '__main__':
   print('call test()')
   test()

Kodu doğrudan python test.py üzerinden çalıştırırsak, modül adı __main__:

 
call test()
test module name=__main__
    
3
2018-05-23 22: 36: 51Z

Tüm cevaplar işlevselliği hemen hemen açıkladı. Ancak, kavramın daha da temizlenmesine yardımcı olabilecek kullanımına bir örnek vereceğim.

İki Python dosyanız olduğunu varsayalım, a.py ve b.py. Şimdi, a.py b.py dosyasını içe aktarır. Önce "import b.py" kodunun çalıştırıldığı a.py dosyasını çalıştırıyoruz. A.py kodunun geri kalanı çalışmadan önce, b.py dosyasındaki kodun tamamen çalışması gerekir.

b.py kodunda, bu b.py dosyasına özel olan bazı kodlar vardır ve b.py dosyasını ithal eden başka bir dosya (b.py dosyası dışında) istemiyoruz Çalıştır.

Demek bu kod satırını kontrol ediyor. Kodu çalıştıran ana dosya (yani, b.py) ise, bu durumda değil (a.py çalışan ana dosyadır), o zaman sadece kod çalıştırılır.

    
3
2018-05-23 22: 38: 56Z

C programlama dilinde main işlevi gibi dosyayı çalıştırmak için giriş noktasıdır.

    
2
2019-02-06 23: 13: 57Z
  1. Bu cevap OP'nin (veya benzer sorusu olan herhangi bir kullanıcının) C ve bir giriş noktasının ne olduğunu bilir.
    2019-02-22 12: 44: 37Z
  2. Bu cevap if __name__ == "__main__" bloğundan önce hiçbir kodun (yan etkisi olmayan tanımlar dışında) yer aldığını varsaymaktadır. Teknik olarak, yürütülen betiğin en üstünde programın giriş noktasıdır.
    2019-04-09 21: 35: 39Z

Python'daki her modül, ad adı verilen bir özniteliğe sahiptir. Modül doğrudan çalıştığında, ad özelliğinin değeri ' ana ' dır. Aksi takdirde, name değeri modülün adıdır.

Kısaca açıklamak için küçük bir örnek.

 
#Script test.py

apple = 42

def hello_world():
    print("I am inside hello_world")

if __name__ == "__main__":
    print("Value of __name__ is: ", __name__)
    print("Going to call hello_world")
    hello_world()

Bu direkt işlemi yapabilirizolarak lyp

 
python test.py  

çıkış

 
Value of __name__ is: __main__
Going to call hello_world
I am inside hello_world

Şimdi, yukarıdaki betiği diğer bültenden çağırdığımızı varsayalım

 
#script external_calling.py

import test
print(test.apple)
test.hello_world()

print(test.__name__)

Bunu yaptığınızda

 
python external_calling.py

çıkış

 
42
I am inside hello_world
test

Öyleyse, yukarıda, diğer komut dosyasından test çağırdığınızda, test.py içindeki name döngüsünün yürütülmeyeceği açıklanmaktadır.

    
1
2019-06-12 09: 28: 39Z
kaynak yerleştirildi İşte