sys.argv
sys.argv[]說白了就是一個從程序外部獲取參數的橋梁。
首先我們需要import sys,sys是python3的一個標准庫,也就是一個官方的模塊。封裝了一些系統的信息和接口,然后再說說argv這個變量。「argv」是「argument variable」參數變量的簡寫形式,一般在命令行調用的時候由系統傳遞給程序。因為我們從外部取得的參數可以是多個,所以獲得的是一個列表(list),也就是說sys.argv其實可以看作是一個列表,所以才能用[]提取其中的元素。其第一個元素是程序本身,即sys.argv[0]是當前所執行的腳本,index 1以后的才是所傳入的參數,用sys.argv[1:]可以獲取到所有的參數,並且輸出到一個列表里面。而切片獲取的參數類型為字符串,即sys.argv傳入的參數為字符串類型,如果想做一些條件判斷的話需要轉成所需要的數據類型。
main()
""Module docstring. This serves as a long usage message. """ import sys import getopt def main(): # parse command line options try: opts, args = getopt.getopt(sys.argv[1:], "h", ["help"]) except getopt.error, msg: print msg print "for help use --help" sys.exit(2) # process options for o, a in opts: if o in ("-h", "--help"): print __doc__ sys.exit(0) # process arguments for arg in args: process(arg) # process() is defined elsewhere if __name__ == "__main__": main()
這樣寫的靈活性還不夠高,尤其是需要解析復雜的命令行選項時。
添加可選的 argv 參數
首先,修改main()函數,使其接受一個可選參數 argv,支持在交互式shell中調用該函數:
def main(argv=None): if argv is None: argv = sys.argv # etc., replacing sys.argv with argv in the getopt() call.
這樣做,我們就可以動態地提供 argv 的值,這比下面這樣寫更加的靈活:
def main(argv=sys.argv): # etc.
因為在調用函數時,sys.argv 的值可能會發生變化;可選參數的默認值都是在定義main()函數時,就已經計算好的。
但是現在sys.exit()
函數調用會產生問題:當main()
函數調用sys.exit()
時,交互式解釋器就會推出!解決辦法是讓main()
函數的返回值指示退出狀態(exit status)。因此,最后面的那行代碼就變成了這樣:
if __name__ == "__main__": sys.exit(main())
定義一個Usage()異常
另一個改進之處,就是定義一個Usage()異常,可以在main()
函數最后的except
子句捕捉該異常:
import sys import getopt class Usage(Exception): def __init__(self, msg): self.msg = msg def main(argv=None): if argv is None: argv = sys.argv try: try: opts, args = getopt.getopt(argv[1:], "h", ["help"]) except getopt.error, msg: raise Usage(msg) # more code, unchanged except Usage, err: print >>sys.stderr, err.msg print >>sys.stderr, "for help use --help" return 2 if __name__ == "__main__": sys.exit(main())
這樣main()
函數就只有一個退出點(exit)了,這比之前兩個退出點的做法要好。而且,參數解析重構起來也更容易:在輔助函數中引發Usage
的問題不大,但是使用return 2
卻要求仔細處理返回值傳遞的問題。
您可能會將try / except子句從main()函數移出到模塊末尾的代碼中(if__name__ ==“__ main__”:......)但這意味着 當你以交互方式調用main()時,但這會引發syntax errors,這不是很有用。
sys.exit() VS os._exit()
sys.exit(n)會引發一個異常:SystemExit,可以捕獲異常執行些清理工作。此處用於捕獲模塊執行結果,如果這個異常沒有被捕獲,那么python解釋器將會退出。如果有捕獲此異常的代碼,那么這些代碼還是會執行。0為正常退出,其他數值(1-127)為不正常,可拋異常事件供捕獲。sys.exit() 用於在主線程中退出。
python的程序有兩中退出方式:os._exit(), sys.exit()。
os._exit()會直接將python程序終止,之后的所有代碼都不會繼續執行。即直接退出, 不拋異常, 不執行相關清理工作。
sys.exit()會引發一個異常:SystemExit,如果這個異常沒有被捕獲,那么python解釋器將會退出。如果有捕獲此異常的代碼,那么這些代碼還是會執行。
一般來說os._exit() 用於在線程中退出,sys.exit() 用於在主線程中退出。
import os try: os._exit(0) except: print("die")
不會打印“die”
try: sys.exit(0) except: print('die') finally: print('cleanup')
輸出:
die
cleanup
區別
綜上,sys.exit()的退出比較優雅,調用后會引發SystemExit異常,可以捕獲此異常做清理工作。os._exit()直接將python解釋器退出,余下的語句不會執行。
一般情況下使用sys.exit()即可,一般在fork出來的子進程中使用os._exit()。
此外,還有exit()/quit() ,exit()跟 C 語言等其他語言的 exit() 應該是一樣的,拋出SystemExit異常。一般在交互式shell中退出時使用。
在很多類型的操作系統里,exit(0) 可以中斷某個程序,而其中的數字參數則用來表示程序是否是碰到錯誤而中斷。exit(1) 表示發生了錯誤,而 exit(0) 則表示程序是正常退出。
這和我們學的布爾邏輯 0==False 正好相反,不過你可以用不一樣的數字表示不同的錯誤結果。比如你可以用exit(100) 來表示另一種和 exit(2)或 exit(1) 不同的錯誤。
【參考文檔】
main函數使用sys.argv傳入多個參數:https://blog.csdn.net/liao392781/article/details/80321614
python 如何寫好main函數:http://codingpy.com/article/guido-shows-how-to-write-main-function/
原文Python main() functions:https://www.artima.com/weblogs/viewpost.jsp?thread=4829
os._exit() vs sys.exit():http://www.cnblogs.com/gaott/archive/2013/04/12/3016355.html
python中exit()的用法:https://blog.csdn.net/Jinger_Warrior/article/details/77628460