name - python__main__用法




如果__name__==“__ main__”:怎麼辦? (18)

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

if __name__ == "__main__":怎麼辦?

__name__是一個全局變量(在Python中,全局實際上意味著在模塊級別上 ),它存在於所有名稱空間中。 它通常是模塊的名稱(作為str類型)。

然而,作為唯一的特殊情況,無論你在哪個Python進程中運行,如在mycode.py中:

python mycode.py

否則,匿名全局命名空間將為其__name__分配值'__main__'

因此,包括最後一行

if __name__ == '__main__':
    main()
  • 在mycode.py腳本的末尾,
  • 當它是由Python進程運行的主要入口點模塊時,

將導致腳本的唯一定義的main函數運行。

使用此構造的另一個好處是:您還可以將代碼作為模塊導入另一個腳本中,然後在程序決定時運行main函數:

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

if __name__ == "__main__":是什麼意思?

概述基礎知識:

  • 作為程序入口點的模塊中的全局變量__name__'__main__' 。 否則,它是您導入模塊的名稱。

  • 因此, if塊下的代碼只有在模塊是程序的入口點時才會運行。

  • 它允許模塊中的代碼可由其他模塊導入,而無需在導入時執行下面的代碼塊。

我們為什麼需要這個?

開發和測試您的代碼

假設您正在編寫一個旨在用作模塊的Python腳本:

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

可以通過將函數的調用添加到底部測試模塊:

do_important()

並運行它(在命令提示符下),例如:

~$ python important.py

問題

但是,如果要將模塊導入另一個腳本:

import important

在導入時,將調用do_important函數,因此您可能會在底部註釋掉函數調用do_important()

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

然後你必須記住你是否已經註釋掉你的測試函數調用。 而這種額外的複雜性意味著您可能會忘記,使您的開發過程更加麻煩。

更好的方式

__name__變量指向Python解釋器恰好在哪裡的命名空間。

在導入的模塊中,它是該模塊的名稱。

但是在主模塊(或交互式Python會話,即解釋器的Read,Eval,Print Loop或REPL)中,您運行的是"__main__"

所以如果你在執行前檢查:

if __name__ == "__main__":
    do_important()

通過上述操作,您的代碼將僅在您將其作為主模塊運行時執行(或有意從其他腳本調用它)。

更好的方式

不過,有一種Pythonic方法可以改進。

如果我們想從模塊外部運行此業務流程怎麼辦?

如果我們在我們開發和測試這樣的函數時放置我們想要運用的代碼,然後在以下之後立即檢查'__main__'

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

我們現在有一個最終函數用於模塊的結束,如果我們將模塊作為主模塊運行,它將運行。

它將允許將模塊及其函數和類導入到其他腳本中而無需運行main函數,並且還允許在從不同的'__main__'模塊運行時調用模塊(及其函數和類),即

import important
important.main()

這個習慣用法也可以在Python文檔的__main__模塊的解釋中找到。 該文字指出:

此模塊表示解釋器主程序執行的(否則為匿名)作用域 - 從標準輸入,腳本文件或交互式提示讀取命令。 正是在這種環境中,慣用的“條件腳本”節導致腳本運行:

if __name__ == '__main__':
    main()

如果name ==' main ':

我們__name__ == '__main__':經常看到。

它檢查是否正在導入模塊。

換句話說,if只有在代碼直接運行時才會執行塊中的代碼。這directly意味著not imported

讓我們看看它使用一個打印模塊名稱的簡單代碼做了什麼:

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

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

如果我們直接運行代碼python test.py,模塊名稱是__main__

call test()
test module name=__main__

__name__變量(imho)的最簡單解釋如下:

創建以下文件。

# a.py
import b

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

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

運行它們會得到這個輸出:

$ python a.py
Hello World from b!

如您所見,在導入模塊時,Python會將此模塊中的globals()['__name__']設置為模塊的名稱。

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

如您所見,在執行文件時,Python將此文件中的globals()['__name__']"__main__"


if __name__ == "__main__"是使用python myscript.py類的命令從命令行運行腳本時運行的部分。


在解釋if __name__ == '__main__'任何內容之前,了解__name__是什麼以及它的作用非常重要。

什麼是__name__

__name__DunderAlias - 可以被認為是一個全局變量(可以從模塊訪問),並以類似於global

它是一個字符串(全局如上所述),由type(__name__) (產生<class 'str'> type(__name__) <class 'str'> ),並且是Python 3Python 2版本的內置標準。

哪裡:

它不僅可以在腳本中使用,還可以在解釋器和模塊/包中找到。

解釋:

>>> print(__name__)
__main__
>>>

腳本:

test_file.py

print(__name__)

導致__main__

模塊或包裝:

somefile.py:

def somefunction():
    print(__name__)

test_file.py:

import somefile
somefile.somefunction()

導致somefile

請注意,在包或模塊中使用時, __name__將獲取文件的名稱。 沒有給出實際模塊或包路徑的路徑,但是它有自己的DunderAlias __file__ ,允許這樣做。

您應該看到, __name__ ,其中主文件(或程序)將始終返回__main__ ,如果它是模塊/包,或者其他任何Python腳本運行,將返回文件的名稱它起源於哪裡。

實踐:

作為變量意味著它的值可以被覆蓋(“可以”並不意味著“應該”),覆蓋__name__的值將導致缺乏可讀性。 所以不要出於任何原因這樣做。 如果需要變量定義新變量。

始終假定__name__的值為__main__或文件名。 再次更改此默認值將導致更多的混淆,它將做好,導致進一步的問題。

例:

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

一般認為在腳本中包含if __name__ == '__main__'是一種好習慣。

現在回答if __name__ == '__main__'

現在我們知道__name__的行為變得更加清晰:

if是一個流控制語句,如果給定的值為true,則包含將執行的代碼塊。 我們已經看到__name__可以使用__main__或從中導入的文件名。

這意味著如果__name__等於__main__那麼該文件必須是主文件,並且必須實際運行(或者它是解釋器),而不是導入到腳本中的模塊或包。

如果確實__name__確實取了__main__的值,那麼該代碼塊中的任何內容都將執行。

這告訴我們如果運行的文件是主文件(或者您直接從解釋器運行),那麼必須執行該條件。 如果它是一個包,那麼它不應該,並且該值不會是__main__

模塊:

__name__也可以在模塊中用於定義模塊的名稱

變種:

使用__name__也可以做其他不太常見但有用的事情,我將在這裡展示一些:

僅在文件是模塊或包時執行:

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

如果文件是主文件,則運行一個條件,如果不是,則運行另一個條件:

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

您還可以使用它在包和模塊上提供可運行的幫助功能/實用程序,而無需精心使用庫。

它還允許模塊作為主腳本從命令行運行,這也非常有用。


在本頁的答案中,我一直在閱讀這麼多內容。 我會說,如果你知道這件事,肯定會理解那些答案,否則,你仍然感到困惑。

簡而言之,您需要了解以下幾點:

  1. import a動作實際運行所有可以在“a”中運行import a動作

  2. 由於第1點,您可能不希望在導入時在“a”中運行所有內容

  3. 要解決第2點中的問題,python允許您進行條件檢查

  4. __name__是所有.py模塊中的隱式變量; 導入__name__ ,a.py模塊的__name__值設置為文件名“a”; 當a.py直接使用“python a.py”運行時,這意味著a.py是入口點,那麼a.py模塊的__name__值設置為字符串__main__

  5. 根據python如何__name__為每個模塊設置變量的機制,你知道如何實現第3點嗎?答案很簡單,對吧?放一個if條件:if __name__ == "__main__": ...; 你可以__name__ == "a"根據你的功能需要放置

python特別重要的是第4點!其餘的只是基本邏輯。


如果此.py文件由其他.py文件導入,則不會執行“if語句”下的代碼。

如果此.py由python this_py.pyshell下運行,或在Windows中雙擊。“if語句”下的代碼將被執行。

它通常是為測試而編寫的。


我認為最好用深入簡單的方式打破答案:

__name__ :Python中的每個模塊都有一個名為__name__的特殊屬性。 它是一個內置變量,它返回模塊的名稱。

__main__ :與其他編程語言一樣,Python也有一個執行入口點,即main。 '__main__' 是頂級代碼執行的範圍的名稱 。 基本上,您有兩種使用Python模塊的方法:直接將其作為腳本運行,或者導入它。 當模塊作為腳本運行時,其__name__設置為__main__

因此,當模塊作為主程序運行時, __name__屬性的值設置為__main__ 。 否則, __name__的值將設置為包含模塊的名稱。


最近,我在創建python(深度學習)課程時遇到了這個問題,並且根據我的理解並同意上面列出的頂級解釋,我將詳細說明

__name__=="__main__"

有時我們在.py文件中構造一個類,並在該類中定義了許多函數。但是我們不想為了一個目的而處理所有這些類函數。例如,用於創建類並定義一些用於數據創建的函數(.npy文件),而一些用於數據加載。所以,如果我們定義

__name__=="__main__"

XXX = CLASS_NAME()

xxx.create_data()

意味著如果我們調用.py文件,那麼它只會創建數據而不會處理其他類函數。其他類函數(數據加載)也可以由其他類導入。


當我們的模塊( M.py )中存在某些語句時,我們希望在它作為main(未導入)運行時執行,我們可以將這些語句(測試用例,打印語句)放在這個if塊下。

默認情況下(當模塊作為main運行,而不是導入時) __name__變量設置為"__main__" ,當它被導入時, __name__變量將獲得不同的值,很可能是模塊的名稱( 'M' )。 這有助於將模塊的不同變體一起運行,並將它們的特定輸入和輸出語句分開,以及是否存在任何測試用例。

簡而言之 ,使用這個' if __name__ == "main" '塊來防止(某些)代碼在導入模塊時運行。


的原因

if __name__ == "__main__":
    main()

主要是為了避免因直接導入代碼而導致的導入鎖定問題。 如果直接調用文件(即__name__ == "__main__"情況),則希望main()運行,但如果導入了代碼,則導入器必須從真正的主模塊輸入代碼以避免導入鎖定問題。

副作用是您自動登錄支持多個入口點的方法。 您可以使用main()作為入口點來運行程序, 但您不必這樣做 。 雖然setup.py需要main() ,但其他工具使用備用入口點。 例如,要將文件作為gunicorn進程運行,請定義app()函數而不是main() 。 與setup.pygunicorn導入您的代碼,因此您不希望它在導入時執行任何操作(因為導入鎖定問題)。


系統(Python解釋器)為源文件(模塊)提供了許多變量。 您可以隨時獲取它們的值,因此,讓我們關注__name__變量/屬性:

當Python加載源代碼文件時,它會執行其中的所有代碼。 (請注意,它不會調用文件中定義的所有方法和函數,但它會定義它們。)

在解釋器執行源代碼文件之前,它為該文件定義了一些特殊變量; __name__是Python為每個源代碼文件自動定義的特殊變量之一。

如果Python將此源代碼文件作為主程序(即您運行的文件)加載,則它會將此文件的特殊__name__變量設置為具有值“__main__”

如果從其他模塊導入,則__name__將設置為該模塊的名稱。

所以,在你的例子中:

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

意味著代碼塊:

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

只有在你直接運行模塊時才會執行; 如果另一個模塊正在調用/導入它,代碼塊將不會執行,因為__name__的值在該特定實例中不等於“ main ”。

希望這會有所幫助。


考慮:

if __name__ == "__main__":
    main()

它檢查Python腳本的__name__屬性是否為"__main__" 。 換句話說,如果程序本身被執行,該屬性將是__main__ ,因此程序將被執行(在這種情況下是main()函數)。

但是,如果模塊使用Python腳本,則會執行if語句之外的任何代碼,因此if \__name__ == "\__main__"來檢查程序是否用作模塊,並且因此決定是否運行代碼。


讓我們以更抽象的方式看待答案:

假設我們在x.py中有這個代碼:

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

當我們運行“x.py”時,塊A和B運行。

但是當我們運行另一個模塊時,只運行塊A(而不是B),例如“y.py”,其中導入了xy並且從那裡運行代碼(就像“x.py”中的函數是從y.py調用。


這裡有很多不同的關於代碼的機制,“如何”,但對我來說,除非我理解“為什麼”,否則它們都沒有意義。 這應該對新程序員特別有用。

取文件“ab.py”:

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

第二個文件“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()

這段代碼到底在做什麼?

執行xy.pyimport ab 。 import語句在導入時立即運行模塊,因此ab的操作在xy的剩餘部分之前執行。 完成ab ,繼續使用xy

解釋器使用__name__跟踪正在運行的腳本。 當您運行腳本時 - 無論您將其命名為什麼 - 解釋器將其稱為"__main__" ,使其成為運行外部腳本後返回的主或“主”腳本。

從此"__main__"腳本調用的任何其他腳本都將其文件名指定為其__name__ (例如, __name__ == "ab.py" )。 因此, if __name__ == "__main__":是解釋器的測試,用於確定它是否正在解釋/解析最初執行的“home”腳本,或者它是否暫時窺視另一個(外部)腳本。 這為程序員提供了靈活性,使腳本的行為不同,如果它直接執行而不是外部調用。

讓我們逐步完成上面的代碼來了解發生了什麼,首先關注的是未縮進的行以及它們在腳本中出現的順序。 請記住,函數 - 或def - 塊在它們被調用之前不會自行執行任何操作。 如果嘟to自己,翻譯可能會說些什麼:

  • 打開xy.py作為“主頁”文件; 在__name__變量中將其__name__"__main__"
  • 使用__name__ == "ab.py"導入並打開文件。
  • 哦,一個功能。 我會記得的。
  • 好的,功能a() ; 我剛學會了這個。 打印' ab文件中函數 '。
  • 文件結束; 回到"__main__"
  • 哦,一個功能。 我會記得的。
  • 另一個。
  • 函數x() ; 好的,打印' 外圍任務:可能在其他項目中很有用 '。
  • 這是什麼? 一個if語句。 好吧,條件已經滿足(變量__name__已設置為"__main__" ),所以我將進入main()函數並打印' main函數:這就是動作的位置 '。

底部兩行表示:“如果這是"__main__"或”home“腳本,則執行名為main()的函數”。 這就是為什麼你會看到一個def main(): block up top,它包含了腳本功能的主要流程。

為什麼實現這個?

還記得我之前說的關於import語句的內容嗎? 導入模塊時,它不僅“識別”它並等待進一步的指令 - 它實際上運行腳本中包含的所有可執行操作。 因此,將腳本的內容放入main()函數中會有效隔離它,將其置於隔離狀態,以便在由另一個腳本導入時不會立即運行。

同樣,會有例外,但通常的做法是main()通常不會被外部調用。 所以你可能想知道另外一件事:如果我們不調用main() ,我們為什麼要調用腳本呢? 這是因為許多人使用獨立函數構建腳本,這些函數構建為獨立於文件中的其餘代碼運行。 然後它們被稱為腳本體內的其他地方。 這讓我想到了這個:

但代碼在沒有它的情況下工作

恩,那就對了。 可以從不包含在main()函數中的內聯腳本調用這些單獨的函數。 如果你已經習慣了(就像我在編程的早期學習階段一樣)構建完全符合你需要的內聯腳本,如果你再次需要這個操作,你會嘗試再次弄清楚它。好吧,你不習慣你的代碼的這種內部結構,因為它構建起來更複雜,而且閱讀不那麼直觀。

但這是一個可能無法在外部調用其函數的腳本,因為如果這樣做,它會立即開始計算和分配變量。 如果你正在嘗試重新使用某個函數,那麼你的新腳本可能與舊版本密切相關,而且會有相互矛盾的變量。

在拆分獨立函數時,您可以通過將它們調用到另一個腳本中來重用以前的工作。 例如,“example.py”可能導入“xy.py”並調用x() ,使用“xy.py”中的“x”函數。 (也許它正在大寫給定文本字符串的第三個單詞;從數字列表中創建NumPy數組並對它們進行平方;或者去除3D表面的去除。可能性是無限的。)

(順便說一句, 這個問題包含@kindall的答案,最終幫助我理解 - 為什麼,而不是如何。不幸的是,它被標記為這個的副本,我認為這是一個錯誤。)


創建一個文件,a.py

print(__name__) # It will print out __main__

__name__始終等於直接運行__main__該文件顯示這是主文件。

在同一目錄中創建另一個文件b.py

import a  # Prints a

運行。它將打印一個,即導入的文件的名稱。

因此,為了顯示同一文件的兩種不同行為,這是一個常用的技巧:

# Code to be run when imported into another python file

if __name__ == '__main__':
    # Code to be run only when run directly

所有答案都解釋了功能。但我將提供一個使用它的例子,這可能有助於進一步清除這個概念。

假設您有兩個Python文件,a.py和b.py. 現在,a.py導入b.py. 我們運行a.py文件,首先執行“import b.py”代碼。在運行其餘的a.py代碼之前,文件b.py中的代碼必須完全運行。

在b.py代碼中,有一些代碼對該文件b.py是獨占的,我們不希望任何導入b.py文件的其他文件(b.py文件除外)運行它。

這就是這行代碼檢查的內容。如果它是運行代碼的主文件(即b.py),在這種情況下它不是(a.py是運行的主文件),那麼只有代碼被執行。







idioms