如何优雅地解析命令行选项随着我们编程经验的增长,对命令行的熟悉程度越来越深,很多人会逐渐体会到使用命令行选项带来的高效命令行。自然地,我们自己编写的很多程序(或者简称为脚本)也希望像原生命令和其他程序一样,可以通过运行时输入的参数来设置和改变程序的行为;配置文件,然后定位到对应的内容,修改,保存,退出……想想就很麻烦好吗?1.手动解析那么我们开始解析命令行参数吧~我们在上一篇关于modules的文章中提到,通过变量sys.args保存了调用当前脚本时传入的命令行参数。我们先观察这个变量:#test_sys.pyimportsysprint(sys.argv)通过命令行调用:$pythontest_sys.py-dtoday-tnow--authorjustdopython--countryChina--auto得到如下输出:['test_sys.py','-d','今天','-t','现在','--author','justdopython','--country','中国','--auto']可以看出,sys.argv实际上是将命令行参数用空格分割得到的字符串列表。此外,第一个命令行参数是当前运行脚本的名称。如果我们要提取每个参数及其对应的值,首先要区分命令行的长参数和短参数,分别以“--”和“-”开头来标识。所以我们也以此作为判断长短参数的条件:importsysforcommand_arginsys.argv[1:]:ifcommand_arg.startswith('--'):print("%s是长参数"%command_arg)elif命令参数。startswith('-'):print("%s是一个短参数"%command_arg)测试结果:$pythonmanually_parse_argv.py-dtoday-tnow--authorjustdopython--countryChina--auto-d是一个短参数parameter-t为短参数--author为长参数--country为长参数--auto为长参数接下来我们需要在解析出长短参数的基础上,分析对应的参数值:#manually_parse_argv.pyimportsys#由于sys.argv的第一个变量是当前脚本的名字,所以跳过index,command_arginenumerate(sys.argv[1:]):ifcommand_arg.startswith('--'):try:value=sys.argv[1:][index+1]ifnotvalue.startswith('-'):print("%s是长参数,参数值为%s"%(command_arg,value))继续exceptIndexError:passprint("%sisalongparameter,noparametervalue"%command_arg)elifcommand_arg.startswith('-'):try:value=sys.argv[1:][index+1]ifnotvalue.startswith('-'):print("%s是短参数,参数值为%s"%(command_arg,value))continueexceptIndexError:passprint("%s是短参数,noparametervalue"%command_arg)再测试一下:$pythonmanually_parse_argv.py-dtoday-tnow--authorjustdopython--countryChina--auto-d是一个短参数,参数值为today-t是一个short参数,且参数值为now--author为长参数,参数值为justdopython--country为长参数,参数值为China--auto为长参数,无参数值好看但看再次atourcode...真正的逻辑还没有开始,已经写了几十行代码来解析命令行参数。这根本不是pythonic——并且不包括一些其他的异常处理。更有什者,每一个类似的程序都需要加入这样的程序。2.getopt模块可以帮助你。Python的优势就是生态太丰富了。几乎每个你想用的函数都已经有人为你写好供你调用。除了梦到衣来伸手饭来张嘴的日子,用Python写程序也不是不可以梦到。例如在命令行参数的解析中,有一个名为getopt的模块,可以准确区分长短命令行参数,也可以正确提取命令行参数的值。我们先来看看:#test_getopt.pyimportsysimportgetoptopts,args=getopt.getopt(sys.argv[1:],'d:t:',["author=","country=","auto"])print(opts)print(args)打印结果:$pythontest_getopt.py-dtoday-tnow--authorjustdopython--countryChina--auto[('-d','today'),('-t','now'),('--author','justdopython'),('--country','China'),('--auto','')][]下面解释一下相关的含义参数。getopt模块中的getopt函数用于解析命令行参数。该函数接受三个参数:args、shortopts和longopts,分别代表“命令行参数”、“接收的短选项”和“接收的长选项”。其中args和longopts是字符串列表,而shortopts是一个字符串。同样,由于sys.argv的第一个值是当前脚本的名称,因此大多数情况下我们会选择将sys.argv[1:]的值传递给args参数。shortopts参数接受的字符串表示需要解析哪些短选项。字符串中的每个字母代表一个短选项:importsysimportgetoptopts,args=getopt.getopt(sys.argv[1:],'dt')print(opts)print(args)output:$pythontest_getopt.py-d-t[('-d',''),('-t','')][]当然,如果输入参数少的话,也不会造成解析失败:$pythontest_getopt.py-t[('-t','')][]但是如果给了一个意外的参数,就会导致模块抛出错误:$pythontest_getopt.py-d-t-kTraceback(mostrecentcalllast):File“test_getopt.py”,第11行,在
