Python __main__ 與程式進入點

在閱讀 Python 程式碼時,你經常會看到這段程式碼:

if __name__ == "__main__":
    main()

這篇文章將解釋這段程式碼的用途,以及 __main__.py 檔案的作用。

if __name__ == "__main__"

__name__ 變數

當 Python 直譯器讀取一個原始碼檔案時,它會設定一些特殊的變數(全域變數),其中之一就是 __name__

__name__ 的值取決於這個腳本是如何被執行的:

  1. 直接執行:如果你直接執行腳本(例如 python my_script.py),__name__ 的值會被設定為 "__main__"
  2. 作為模組匯入:如果你在其他腳本中匯入這個檔案(例如 import my_script),__name__ 的值會是模組名稱("my_script")。

用途

這段判斷式的主要目的是:讓檔案既可以被當作腳本直接執行,又可以當作模組被匯入,而不會執行不該執行的程式碼

範例 calculator.py

def add(a, b):
    return a + b

def main():
    print("Running calculator demo:")
    print(f"2 + 3 = {add(2, 3)}")

if __name__ == "__main__":
    # 只有在直接執行這個檔案時,才會執行 main()
    # 如果被 import,這裡的程式碼不會跑
    main()
  • 執行 python calculator.py:

    • __name__"__main__"
    • 條件成立,執行 main()
    • 輸出 demo 結果
  • 執行 import calculator:

    • __name__"calculator"
    • 條件不成立
    • add 函數被定義並可以被使用,但 main() 不會自動執行

__main__.py 檔案

__main__.py 是一個特殊的檔案,用來讓 Python 套件 (Package) 或目錄變成「可直接執行」的。

假設你有以下目錄結構:

myapp/
    __init__.py
    core.py
    __main__.py

執行目錄

如果 myapp 目錄下包含 __main__.py,你可以直接執行整個目錄:

python myapp

Python 會自動尋找並執行 myapp/__main__.py

使用 -m 模組模式

同樣的,如果你安裝了一個套件,也可以用 -m 參數執行它(這也會執行該套件的 __main__.py):

python -m myapp

這在開發 CLI 工具(命令列工具)時非常有用。例如 pip 本身就是這樣運作的:

python -m pip install requests

這實際上是在執行 pip 套件中的 __main__.py

最佳實踐

建議將主要的執行邏輯封裝在 main() 函數中,保持全域作用域乾淨:

import sys

def main(args):
    # 主程式邏輯
    print(f"Arguments: {args}")
    return 0

if __name__ == "__main__":
    # 將命令列參數傳給 main,並使用回傳值作為 exit code
    sys.exit(main(sys.argv[1:]))