使用特定选项时,python argparse忽略其他选项 [英] python argparse ignore other options when a specific option is used
问题描述
我正在编写一个Python程序,希望它具有以特定方式运行的命令行界面
I am writing a python program that I want to have a command line interface that behaves in a particular way
命令行界面应接受以下调用:
The command line interface should accept the following invocations:
my_prog test.svg foo
my_prog --font=Sans test.svg foo
(它将以指定或默认字体写入带有 foo
字的svg)
(it will generate an svg with the word foo
written in the specified or default font)
现在,我希望也能使该命令接受以下调用...
Now I want to be able to also have this command accept the following invocation...
my_prog --list-fonts
,它将列出-font
的所有有效选项,具体取决于系统上可用的字体.
which will list all of the valid options to --font
as determined by the fonts available on the system.
我正在使用 argparse
,并且我有这样的东西:
I am using argparse
, and I have something like this:
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
选项的行为如我所愿,因为仍然需要两个位置参数.
however this does not make the --list-fonts
option behave as I would like as the two positional arguments are still required.
我也尝试过使用子解析器,但是仍然需要一种变通方法以防止每次都需要其他选项.
I have also tried using subparsers, but these still need a workaround to prevent the other options being required every time.
如何使用argparse获得所需的行为.
How do I get the desired behaviour with argparse.
推荐答案
通过argparse,您可以基于 add_argument
(查看文档)
argparse allows you to define arbitrary actions to take when encountering an argument, based on the action
keyword argument to add_argument
(see the docs)
您可以定义一个动作来列出字体,然后中止参数解析,这样可以避免检查其他必需的参数.
You can define an action to list your fonts and then abort argument parsing, which will avoid checking for the other required arguments.
这可能看起来像这样:
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
然后您可以将其添加到您的参数中,如下所示:
Then you can add it to your argument like so:
parser.add_argument('--list-fonts', nargs=0, action=ListFonts)
注意 nargs = 0
已添加,因此该参数不需要值(问题中的代码通过 action ='store_true'
实现此目的)
Note nargs=0
has been added so that this argument doesn't require a value (the code in the question achieved this with action='store_true'
)
此解决方案具有一个副作用,即可以在不运行主程序的情况下使如下所示的调用也列出字体和退出项:
This solution has a side-effect of enabling the invocations like the following to also list the fonts and exits without running the main program:
my_prog --font Sans test.svg text --list-fonts
这可能不是问题,因为它不是典型的用例,特别是如果帮助文本解释了这种行为.
This is likely not a problem as it's not a typical use case, especially if the help text explains this behaviour.
如果为每个这样的选项定义一个新类感觉太过沉重,或者您可能不止一个具有这种行为的选项,那么您可以考虑使用一个为每个参数实现所需操作的函数,然后使用一种返回包装该函数的类的工厂函数.完整的示例如下所示.
If defining a new class for each such option feels too heavyweight, or perhaps you have more than one option that has this behaviour, then you could consider having a function that implements the desired action for each argument and then have a kind of factory function that returns a class that wraps the function. A complete example of this is shown below.
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()
这篇关于使用特定选项时,python argparse忽略其他选项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!