我正在编写一个Python程序,希望它具有以特定方式运行的命令行界面
命令行界面应接受以下调用:
my_prog test.svg foo
my_prog --font=Sans test.svg foo
(它将以指定或默认字体写有单词foo
的svg)
现在,我希望也可以使该命令接受以下调用...
my_prog --list-fonts
它将列出--font
的所有有效选项,具体取决于系统上可用的字体。
我正在使用argparse
,并且我有类似这样的内容:
parser = argparse.ArgumentParser()
parser.add_argument('output_file')
parser.add_argument('text')
parser.add_argument('--font', help='list options with --list-fonts')
parser.add_argument('--list-fonts', action='store_true')
args = parser.parse_args()
但是,这仍然无法使--list-fonts
选项的行为正常,因为仍然需要两个位置参数。
我也尝试过使用子解析器,但是仍然需要一种变通方法以防止每次都需要其他选项。
如何使用argparse获得所需的行为。
答案 0 :(得分:1)
argparse允许您基于action
(see the docs)的add_argument
关键字参数来定义遇到参数时要采取的任意操作
您可以定义一个动作来列出字体,然后中止参数解析,这样可以避免检查其他必需的参数。
这可能看起来像这样:
class ListFonts(argparse.Action):
def __call__(self, parser, namespace, values, option_string):
print("list of fonts here")
parser.exit() # exits the program with no more arg parsing and checking
然后您可以将其添加到参数中,如下所示:
parser.add_argument('--list-fonts', nargs=0, action=ListFonts)
注意nargs=0
已添加,因此该参数不需要值(问题中的代码通过action='store_true'
实现了此目的)
此解决方案具有一个副作用,即无需运行主程序即可启用如下所示的调用来列出字体和退出项:
my_prog --font Sans test.svg text --list-fonts
这可能不是问题,因为它不是典型的用例,特别是如果帮助文本解释了这种行为。
如果为每个这样的选项定义一个新类感觉太过沉重,或者您可能不止一个具有这种行为的选项,那么您可以考虑使用一个为每个参数实现所需操作的函数,然后使用一种工厂函数返回包装该函数的类。完整的示例如下所示。
def list_fonts():
print("list of fonts here")
def override(func):
""" returns an argparse action that stops parsing and calls a function
whenever a particular argument is encountered. The program is then exited """
class OverrideAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string):
func()
parser.exit()
return OverrideAction
parser = argparse.ArgumentParser()
parser.add_argument('output_file')
parser.add_argument('text')
parser.add_argument('--font', help='list options with --list-fonts')
parser.add_argument('--list-fonts', nargs=0, action=override(list_fonts),
help='list the font options then stop, don\'t generate output')
args = parser.parse_args()