日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網營銷解決方案
創(chuàng)新互聯(lián)Python教程:__main__—-最高層級代碼環(huán)境

__main__ —- 最高層級代碼環(huán)境


在 python 中,特殊名稱 __main__ 被用于兩個重要的構造:

創(chuàng)新互聯(lián)公司擁有十余年成都網站建設工作經驗,為各大企業(yè)提供網站設計、網站建設服務,對于網頁設計、PC網站建設(電腦版網站建設)、重慶App定制開發(fā)、wap網站建設(手機版網站建設)、程序開發(fā)、網站優(yōu)化(SEO優(yōu)化)、微網站、申請域名等,憑借多年來在互聯(lián)網的打拼,我們在互聯(lián)網網站建設行業(yè)積累了很多網站制作、網站設計、網絡營銷經驗,集策劃、開發(fā)、設計、營銷、管理等網站化運作于一體,具備承接各種規(guī)模類型的網站建設項目的能力。

  1. 程序的最高層級環(huán)境的名稱,可以使用 __name__ == '__main__' 表達式來檢查它;以及

  2. Python 包中的 __main__.py 文件。

這兩種機制都有 Python 模塊有關;用戶如何與它們交互以及它們之間如何交互。 下文將進行詳細說明。 如果你還不了解 Python 模塊,請查看教程 模塊 一節(jié)的介紹。

__name__ == '__main__'

當一個 Python 模塊或包被導入時,__name__ 會被設為模塊的名稱。 通常,這將是 Python 文件本身的名稱去掉 .py 后綴:

 
 
 
 
  1. >>> import configparser
  2. >>> configparser.__name__
  3. 'configparser'

如果文件是包的組成部分,則 __name__ 還將包括父包的路徑:

 
 
 
 
  1. >>> from concurrent.futures import process
  2. >>> process.__name__
  3. 'concurrent.futures.process'

不過,如果模塊是在最高層級代碼環(huán)境中執(zhí)行的,則它的 __name__ 會被設為字符串 '__main__'。

什么是“最高層級代碼環(huán)境”?

__main__ 是最高層級代碼運行所在環(huán)境的名稱。 “最高層級代碼”即用戶指定最先啟動運行的 Python 模塊。 它被稱為“最高層級”是因為它將導入程序所需的所有其他模塊。 有時“最高層級代碼”也被稱為應用的 入口點。

最高層級代碼環(huán)境可以是:

  • 一個交互提示符的作用域:

       
       
       
       
    1. >>> __name__
    2. '__main__'
  • 作為文件參數(shù)傳給 Python 解釋器的 Python 模塊:

        
        
        
        
    1. $ Python3 helloworld.py
    2. Hello, world!
  • 作為 -m 參數(shù)傳給 Python 解釋器的 Python 模塊或包:

        
        
        
        
    1. $ python3 -m tarfile
    2. usage: tarfile.py [-h] [-v] (...)
  • Python 解釋器從標準輸入中讀取的 Python 代碼:

        
        
        
        
    1. $ echo "import this" | python3
    2. The Zen of Python, by Tim Peters
    3. Beautiful is better than ugly.
    4. Explicit is better than implicit.
    5. ...
  • 作為 -c 參數(shù)傳遞給 Python 解釋器的 Python 代碼:

        
        
        
        
    1. $ python3 -c "import this"
    2. The Zen of Python, by Tim Peters
    3. Beautiful is better than ugly.
    4. Explicit is better than implicit.
    5. ...

在以上每個情形中,頂級模塊的 __name__ 被設置為 '__main__'

因此,一個模塊可以通過檢查自己的 __name__ ,來發(fā)現(xiàn)它是否在頂層環(huán)境中運行。這是允許在模塊沒有從導入語句中初始化的情況下,有條件地執(zhí)行代碼的一個常見的語句:

 
 
 
 
  1. if __name__ == '__main__':
  2. # Execute when the module is not initialized from an import statement.
  3. ...

參見

關于在所有情況下 __name__ 是如何設置的細節(jié),請看教程部分 模塊 。

常見用法

有些模塊包含了僅供腳本使用的代碼,比如解析命令行參數(shù)或從標準輸入獲取數(shù)據(jù)。 如果這樣的模塊被從不同的模塊中導入,例如為了單元測試,腳本代碼也會無意中執(zhí)行。

這就是 if __name__ == '__main__' 代碼塊的用武之地。除非模塊在頂層環(huán)境中被執(zhí)行,否則該塊內的代碼不會運行。

將盡可能少的語句放在下面的 if __name___ == '__main__' 塊中可以提高代碼的清晰度和正確性。最常見的,一個名為 main 的函數(shù)封裝了程序的主要行為:

 
 
 
 
  1. # echo.py
  2. import shlex
  3. import sys
  4. def echo(phrase: str) -> None:
  5. """A dummy wrapper around print."""
  6. # for demonstration purposes, you can imagine that there is some
  7. # valuable and reusable logic inside this function
  8. print(phrase)
  9. def main() -> int:
  10. """Echo the input arguments to standard output"""
  11. phrase = shlex.join(sys.argv)
  12. echo(phrase)
  13. return 0
  14. if __name__ == '__main__':
  15. sys.exit(main()) # next section explains the use of sys.exit

請注意,如果模塊沒有將代碼封裝在 main 函數(shù)內,而是直接放在 if __name__ == '__main__' 塊內,那么這個 phrase 變量對整個模塊來說就是全局變量。 這很容易出錯,因為模塊內的其他函數(shù)可能會無意中使用全局變量而不是局部名稱。 一個 main 函數(shù)解決了這個問題。

使用 main 函數(shù)有一個額外的好處,就是 echo 函數(shù)本身是孤立的,可以在其他地方導入。當 echo.py 被導入時,echomain 函數(shù)將被定義,但它們都不會被調用,因為 __name__ != '__main__' 。

打包考量

main 函數(shù)經常被用來創(chuàng)建命令行工具,把它們指定為控制臺腳本的入口點。 當這樣做時,pip 將函數(shù)調用插入到模板腳本中,其中 main 的返回值被傳遞到 sys.exit() 。例如:

 
 
 
 
  1. sys.exit(main())

由于 main 調用被包裹在 sys.exit() 中,期望你的函數(shù)將返回一些可被 sys.exit() 作為輸入而接受的值;通常為一個整數(shù)或 None (如果你的函數(shù)沒有返回語句,則隱含返回)。

通過主動遵循這一慣例,我們的模塊在直接運行時(即 python3 echo.py )會有相同的行為,如果我們以后把它打包成可用 pip 安裝的包中的控制臺腳本入口,它也會有相同的行為。

特別的是,要小心從你的 main 函數(shù)中返回字符串。 sys.exit() 將把一個字符串參數(shù)解釋為失敗信息,所以你的程序將有一個 1 的退出代碼,表示失敗。并且這個字符串將被寫入 sys.stderr 。 前面的 echo.py 例子舉例說明了使用 sys.exit(main()) 的約定。

參見

Python 打包用戶指南 包含了一系列關于如何用現(xiàn)代工具分發(fā)和安裝 Python 包的教程和參考資料。

Python 包中的 __main__.py

如果你不熟悉Python包,請參閱本教程的 包 一節(jié)。最常見的是, __main__.py 文件被用來為一個包提供命令行接口。假設有下面這個虛構的包,”bandclass”:

 
 
 
 
  1. bandclass
  2. ├── __init__.py
  3. ├── __main__.py
  4. └── student.py

當使用 -m 標志從命令行直接調用軟件包本身時,將執(zhí)行 __main__.py 。比如說。

 
 
 
 
  1. $ python3 -m bandclass

這個命令將導致 __main__.py 的運行。你如何利用這一機制將取決于你所編寫的軟件包的性質,但在這個假設的案例中,允許教師搜索學生可能是有意義的:

 
 
 
 
  1. # bandclass/__main__.py
  2. import sys
  3. from .student import search_students
  4. student_name = sys.argv[2] if len(sys.argv) >= 2 else ''
  5. print(f'Found student: {search_students(student_name)}')

注意, from .student import search_students 是一個相對導入的例子。 這種導入方式可以在引用一個包內的模塊時使用。 更多細節(jié),請參見教程 模塊 中的 子包參考 一節(jié)。

常見用法

__main__.py 的內容通常不是用 if __name__ == '__main__' 區(qū)塊圍起來的。 相反,這些文件保持簡短,功能從其他模塊執(zhí)行。 那些其他模塊可以很容易地進行單元測試,并且可以適當?shù)刂貜褪褂谩?/p>

如果使用,一個 if __name__ == '__main__' 區(qū)塊仍然會像預期的那樣對包內的 __main__.py 文件起作用,因為如果導入,它的 __name__ 屬性將包括包的路徑:

 
 
 
 
  1. >>> import asyncio.__main__
  2. >>> asyncio.__main__.__name__
  3. 'asyncio.__main__'

但這對 .zip 文件的根目錄中的 __main__.py 文件不起作用。 因此,為了保持一致性,像下面提到的 venv 這樣的最小 __main__.py 是首選。

參見

參見 venv 以了解標準庫中最小 __main__.py 的軟件包示例。它不包含一個 if __name__ == '__main__' 塊。你可以用 python3 -m venv [directory] 調用它。

參見 runpy 以了解更多關于 -m 標志對解釋器可執(zhí)行包的細節(jié)。

參見 zipapp 了解如何運行打包成 .zip 文件的應用程序。在這種情況下,Python 會在歸檔文件的根目錄下尋找一個 __main__.py 文件。

import __main__

不管 Python 程序是用哪個模塊啟動的,在同一程序中運行的其他模塊可以通過導入 __main__ 模塊來導入頂級環(huán)境的范圍 ( namespace )。這并不是導入一個 __main__.py 文件,而是導入使用特殊名稱 '__main__' 的哪個模塊。

下面是一個使用 __main__ 命名空間的模塊的例子:

 
 
 
 
  1. # namely.py
  2. import __main__
  3. def did_user_define_their_name():
  4. return 'my_name' in dir(__main__)
  5. def print_user_name():
  6. if not did_user_define_their_name():
  7. raise ValueError('Define the variable `my_name`!')
  8. if '__file__' in dir(__main__):
  9. print(__main__.my_name, "found in file", __main__.__file__)
  10. else:
  11. print(__main__.my_name)

該模塊的用法示例如下:

 
 
 
 
  1. # start.py
  2. import sys
  3. from namely import print_user_name
  4. # my_name = "Dinsdale"
  5. def main():
  6. try:
  7. print_user_name()
  8. except ValueError as ve:
  9. return str(ve)
  10. if __name__ == "__main__":
  11. sys.exit(main())

現(xiàn)在,如果我們啟動我們的程序,結果會是這樣的:

 
 
 
 
  1. $ python3 start.py
  2. Define the variable `my_name`!

該程序的退出代碼為 1 ,表明有錯誤。取消對 my_name = "Dinsdale" 這一行的注釋,就可以修復程序,現(xiàn)在它的退出狀態(tài)代碼為 0 ,表示成功。

 
 
 
 
  1. $ python3 start.py
  2. Dinsdale found in file /path/to/start.py

請注意,導入 __main__ 不會導致無意中運行旨在用于腳本的頂層代碼的問題,這些代碼被放在模塊 startif __name__ == "__main__" 塊中。為什么這樣做?

Python 解釋器啟動時會在 sys.modules 中插入一個空的 __main__ 模塊,并通過運行頂層代碼來填充它。 在我們的例子中這就是 start 模塊,它逐行運行并導入 namely。 反過來,namely 會導入 __main__ (這其實是 start)。 這就是一個導入循環(huán)! 幸運的是,由于部分填充的 __main__ 模塊存在于 sys.modules 中,Python 會將其傳遞給 namely。 請參閱導入系統(tǒng)參考資料中 有關 __main__ 的特別考量 來了解其中的詳情。

Python REPL 是另一個 “頂層環(huán)境 “的例子,所以在 REPL 中定義的任何東西都成為 __main__ 范圍的一部分:

 
 
 
 
  1. >>> import namely
  2. >>> namely.did_user_define_their_name()
  3. False
  4. >>> namely.print_user_name()
  5. Traceback (most recent call last):
  6. ...
  7. ValueError: Define the variable `my_name`!
  8. >>> my_name = 'Jabberwocky'
  9. >>> namely.did_user_define_their_name()
  10. True
  11. >>> namely.print_user_name()
  12. Jabberwocky

注意,在這種情況下, __main__ 范圍不包含 __file__ 屬性,因為它是交互式的。

__main__ 范圍用于 pdb 和 rlcompleter 的實現(xiàn)。


分享名稱:創(chuàng)新互聯(lián)Python教程:__main__—-最高層級代碼環(huán)境
當前路徑:http://m.5511xx.com/article/dppepej.html