Mark Roddy 的解决方案可以工作,但它需要在运行时修改解析器对象的属性,并且不支持 - 或 - 以外的替代选项格式。一个稍微少一些的解决方案是在运行 optparse 之前修改 sys.argv 数组,并在不需要参数的开关之后插入一个空字符串 ("")。此方法的唯一限制是您的选项默认为一个可预测的值,而不是插入到 sys.argv 中的值(我在下面的示例中选择了 None,但这并不重要)。
下面的代码创建一个示例解析器和一组选项,从解析器中提取一个允许的开关数组(使用一点实例变量魔法),然后遍历 sys.argv,每次找到一个允许的开关,它检查它是否是在没有任何参数的情况下给出的。如果切换后没有参数,则将在命令行中插入空字符串。修改 sys.argv 后,解析器被调用,您可以检查值为 "" 的选项,并采取相应的行动。
#Instantiate the parser, and add some options; set the options' default values to None, or something predictable that
#can be checked later.
PARSER_DEFAULTVAL = None
parser = OptionParser(usage="%prog -[MODE] INPUT [options]")
#This method doesn't work if interspersed switches and arguments are allowed.
parser.allow_interspersed_args = False
parser.add_option("-d", "--delete", action="store", type="string", dest="to_delete", default=PARSER_DEFAULTVAL)
parser.add_option("-a", "--add", action="store", type="string", dest="to_add", default=PARSER_DEFAULTVAL)
#Build a list of allowed switches, in this case ['-d', '--delete', '-a', '--add'] so that you can check if something
#found on sys.argv is indeed a valid switch. This is trivial to make by hand in a short example, but if a program has
#a lot of options, or if you want an idiot-proof way of getting all added options without modifying a list yourself,
#this way is durable. If you are using OptionGroups, simply run the loop below with each group's option_list field.
allowed_switches = []
for opt in parser.option_list:
#Add the short (-a) and long (--add) form of each switch to the list.
allowed_switches.extend(opt._short_opts + opt._long_opts)
#Insert empty-string values into sys.argv whenever a switch without arguments is found.
for a in range(len(sys.argv)):
arg = sys.argv[a]
#Check if the sys.argv value is a switch
if arg in allowed_switches:
#Check if it doesn't have an accompanying argument (i.e. if it is followed by another switch, or if it is last
#on the command line)
if a == len(sys.argv) - 1 or argv[a + 1] in allowed_switches:
sys.argv.insert(a + 1, "")
options, args = parser.parse_args()
#If the option is present (i.e. wasn't set to the default value)
if not (options.to_delete == PARSER_DEFAULTVAL):
if options.droptables_ids_csv == "":
#The switch was not used with any arguments.
...
else:
#The switch had arguments.
...