翻譯:《實用的Python編程》03_05_Main_module
- 2021 年 3 月 5 日
- 筆記
- Python, 實用的Python編程
目錄 | 上一節 (3.4 模組) | 下一節 (3.6 設計討論)
3.5 主模組
本節介紹主程式(主模組)的概念
主函數
在許多程式語言中,存在一個主函數或者主方法的概念。
// c / c++
int main(int argc, char *argv[]) {
...
}
// java
class myprog {
public static void main(String args[]) {
...
}
}
這是啟動應用程式時執行的第一個函數。
Python 主模組
Python 沒有主函數(main function)或主方法(main method)。相反,Python 有一個主模組(main
module)。主模組是第一個運行的源文件。
bash % python3 prog.py
...
在應用程式啟動時,提供給解釋器的任何文件都將成為主模組。名字並不重要。
__main__
檢查
對於作為主腳本運行的模組,使用此約定(譯註:__main__
檢查)是標準做法。
# prog.py
...
if __name__ == '__main__':
# Running as the main program ...
statements
...
在 if
裡面的語句稱為主程式( main program)。
主程式與庫導入
任何 Python 文件都可以作為主程式運行,或者作為一個庫(譯註:library,在 Python 中 library 既可以指模組 module,也可以指包 package),導入後運行。
bash % python3 prog.py # Running as main
import prog # Running as library import
在這兩種情況下,__name__
都是模組的名稱(譯註:prog)。然而,如果作為主程式運行,__name__
只能被設置為 __main__
。
通常,我們不希望主程式中的語句在庫導入的時候執行。所以,通常在程式碼中包含一個 if-
檢查,判斷當前文件是否是主程式(譯註:如果當前程式不是主程式,則 if __name__ == '__main__':
裡面的語句不執行)。
if __name__ == '__main__':
# Does not execute if loaded with import ...
程式模板
這裡有一個用於編寫 Python 程式的通用模板:
# prog.py
# Import statements (libraries)
import modules
# Functions
def spam():
...
def blah():
...
# Main function
def main():
...
if __name__ == '__main__':
main()
命令行工具
Python 通常在命令行工具中使用:
bash % python3 report.py portfolio.csv prices.csv
這意味著腳本在 shell 或者 終端(terminal)執行。通常用於自動化,後台任務等。
命令行參數
命令行參數是一個文本字元串列表。
bash % python3 report.py portfolio.csv prices.csv
該文本字元串列表可以在 sys.argv
中找到。
# In the previous bash command
sys.argv # ['report.py, 'portfolio.csv', 'prices.csv']
這裡有一個處理參數的簡單示例:
import sys
if len(sys.argv) != 3:
raise SystemExit(f'Usage: {sys.argv[0]} ' 'portfile pricefile')
portfile = sys.argv[1]
pricefile = sys.argv[2]
...
標準 I/O
標準輸入/輸出(或者stdio)是和普通文件使用相同工作方式的文件。
sys.stdout
sys.stderr
sys.stdin
默認情況下,列印定向到 sys.stdout
文件。輸入是從 sys.stdin
文件讀取。回溯和錯誤定向到 sys.stderr
文件。
請注意,標準輸入/輸出(stdio)可以連接到終端(terminals),文件(files),管道(pipes)等。
bash % python3 prog.py > results.txt
# or
bash % cmd1 | python3 prog.py | cmd2
環境變數
環境變數在 shell 中設置。
bash % setenv NAME dave
bash % setenv RSH ssh
bash % python3 prog.py
os.environ
是包含這些值的字典。
import os
name = os.environ['NAME'] # 'dave'
更改會反映在程式隨後啟動的任何子進程中。
程式退出
通過異常處理程式退出。
raise SystemExit
raise SystemExit(exitcode)
raise SystemExit('Informative message')
其它方式。
import sys
sys.exit(exitcode)
非零(non-zero )退出碼錶示錯誤。
#!
行
在 Unix 系統中,#!
行指定某個路徑下的 Python 解釋器來執行該腳本(譯註:#!
稱為 Shebang 或者 hashbang,因為 # 號通常稱為 hash 或者 sharp,而 ! 號則常常稱為 bang)。將以下內容添加到腳本文件的第一行。
#!/usr/bin/env python3
# prog.py
...
(譯註:#!/usr/bin/env python3
的意思——到 Unix 系統 env 所包含的全部環境變數中尋找 Python3 解釋器,並使用 Python3 解釋器執行該腳本)
執行腳本需要腳本具有可執行許可權。
bash % chmod +x prog.py
# Then you can execute
bash % prog.py
... output ...
注意:Windows 系統上的 Python 啟動器也會尋找 #!
行以指示語言版本。
腳本模板
最後,這裡有一個通用程式碼模板,用於將 Python 程式作為命令行腳本運行:
#!/usr/bin/env python3
# prog.py
# Import statements (libraries)
import modules
# Functions
def spam():
...
def blah():
...
# Main function
def main(argv):
# Parse command line args, environment, etc.
...
if __name__ == '__main__':
import sys
main(sys.argv)
練習
練習 3.15:main()
函數
在 report.py
文件中添加一個 main()
函數,該函數接受命令行選項列表,並生成與以前相同的輸出。修改後,應該能夠像下面這樣交互地運行它:
>>> import report
>>> report.main(['report.py', 'Data/portfolio.csv', 'Data/prices.csv'])
Name Shares Price Change
---------- ---------- ---------- ----------
AA 100 9.22 -22.98
IBM 50 106.28 15.18
CAT 150 35.46 -47.98
MSFT 200 20.89 -30.34
GE 95 13.48 -26.89
MSFT 50 20.89 -44.21
IBM 100 106.28 35.84
>>>
請修改 pcost.py
文件,添加一個類似的 main()
函數。
>>> import pcost
>>> pcost.main(['pcost.py', 'Data/portfolio.csv'])
Total cost: 44671.15
>>>
練習 3.16:編寫腳本
請修改 report.py
和 pcost.py
程式,以便它們在命令行上可以作為腳本執行:
bash $ python3 report.py Data/portfolio.csv Data/prices.csv
Name Shares Price Change
---------- ---------- ---------- ----------
AA 100 9.22 -22.98
IBM 50 106.28 15.18
CAT 150 35.46 -47.98
MSFT 200 20.89 -30.34
GE 95 13.48 -26.89
MSFT 50 20.89 -44.21
IBM 100 106.28 35.84
bash $ python3 pcost.py Data/portfolio.csv
Total cost: 44671.15