一、说明
在学C语言的时候就知道可以通过argc获取命令行参数个数,可以通过argv获取具体参数。但自己写的程序获取到的参数一是没有键值形式二是写的参数不能乱序,和系统命令不太一样。
但这种位置参数用起来还是很不方便的,还是很有必要弄清系统命令的那种参数该如何实现。这里我们介绍经典的getopt和pythonic的argparse。
二、getopt实现
2.1 程序代码
此程序中设置-h/-n/-p三个选项,-h不带值-n和-p带值;三个参数设置等价长格式--help/--name/--profession。
程序通过sys.argv[1:]来获取所有待解析参数,然后传到getopt进行解析,更多说明见代码注释。
import getopt import sys def _parse_option(): try: # 第一个参数argv----传过来的要解析的参数数组。形如['-n', 'ls', '-p', 'programmer'] # 第二个参数"hn:p:"----用于向getopt注册短格式。没有:表示该参数不带值,有:表示下一参数为该参数的值 # 第三个参数[]----用于向getopt注册长格式。没有=表示该参数不带值,有=表示=号后边为其值(如果没有=号就以下一个参数为其值) # 第三个参数[]----[]不是可选的意思,这里是代码,[]表示该参数是个数组 # opts----以元组形式存放解析出的参数。形如[('-n', 'ls'), ('-p', 'programmer'), ('-h', '')] # args----以数组形式存放按所有注册的格式未能解析参数 # 系统参数可通过sys.argv[index]来获取,sys.argv[0]是本身文件名 print(f"will parse argv: {sys.argv[1:]}") opts, args = getopt.getopt(sys.argv[1:], "hn:p:", ["help", "name=", "profession="]) print(f"parsed argv: opts----{opts} args----{args}") except getopt.GetoptError: # 参数不符合注册格式要求报错 print("parameter format error") _usage() sys.exit(2) options_dict = {} # 遍历所有元组 # getopt只会严格按照注册的格式解析参数,而不理解哪个短格式与哪个长格式等价,等价是我们这里设定短格式和长格式用同一响应造成的 # 也就是说getopt并不理解-n和--name等价,他有-n就解析-n有--name就解析--name,两个都有就两个都解析。-n和--name等价是因为我们对这两个参数用同样的代码进行处理。 # 比如执行python getopt_test.py -n ls --name=root,解析出的就是[('-n', 'ls'), ('--name', 'root')] for opt, arg in opts: # -h与--help等价 if opt in ("-h", "--help"): _usage() sys.exit() # -n与--name等价 elif opt in ("-n", "--name"): options_dict["user_name"] = arg # -p与--profession等价 elif opt in ("-p", "--profession"): options_dict["user_profession"] = arg return options_dict, args def _usage(): print("getopt_test version 1.0") print("-h print this message") print("-n <your name> equ --name") print("-p <your profession> equ --profession") class TestGetopt: """ sys.argv[index]武断地以空格来划分参数,并不能区分选项和选项值 sys.argv[index]不能乱序,取第一个参数为用户名,就必须在第一个参数输入用户名,不能在第二或别的地方输 我们使用getopt模块来解决这两个问题 """ def __init__(self): self.options_dict, self.args = _parse_option() def test_use_arg(self): print(f"options: {self.options_dict}") print(f"args: {self.args}") print(f"you are {self.options_dict['user_profession']} {self.options_dict['user_name']}!") if __name__ == "__main__": obj = TestGetopt() obj.test_use_arg()