如何在 python 中编写 argparse 组合选项

发布于 2024-10-31 10:48:45 字数 2496 浏览 0 评论 0原文

我一直为完成这个小小的活动而烦恼。我确实做了一些实验,但未能达到结果。

要求:

   test2.py [-c/-v] -f

用法或规则:

  1. -c(比较)需要 2 个参数。

    -v(验证)采用 1 个参数。

    这两者之一必须存在,但不能同时存在

  2. -f 是强制参数(输出文件名)。

输出:

我能够获得所需的输出,如下所示

kp@kp:~/Study/scripts$ ./test.py -c P1 P2 -f p
kp@kp:~/Study/scripts$ ./test.py -v P1 -f p
kp@kp:~/Study/scripts$ ./test.py -v P1 
usage: test.py <functional argument> <ouput target argument>
test.py: error: argument -f/--file is required
kp@kp:~/Study/scripts$ ./test.py -c P1 P2 
usage: test.py <functional argument> <ouput target argument>
test.py: error: argument -f/--file is required
kp@kp:~/Study/scripts$ 

问题是:

当您使用时,test.py -h
1. 输出不会表明 -c/-v 其中任何一个是强制的,但不是两者都强制 。它表示所有参数都是可选的。
2. 输出将指示可选参数下的 -f 选项,这是不正确的。 -f 是强制参数,我想显示外部 - 可选参数。

如何更改脚本以使 -h 选项输出更加用户友好(无需任何外部验证)

usage: test.py <functional argument> <ouput target argument>

Package Compare/Verifier tool.

optional arguments:
  -h, --help            show this help message and exit
  -f outFileName, --file outFileName
                        File Name where result is stored.
  -c Package1 Package2, --compare Package1 Package2
                        Compare two packages.
  -v Package, --verify Package
                        Verify Content of package.
kiran@kiran-laptop:~/Study/scripts$ 

代码:

我正在使用以下代码来实现输出,

#!/usr/bin/python

import sys
import argparse

def main():
    usage='%(prog)s <functional argument> <ouput target argument>'
    description='Package Compare/Verifier tool.'
    parser = argparse.ArgumentParser(usage=usage,description=description)

    parser.add_argument('-f','--file',action='store',nargs=1,dest='outFileName',help='File Name where result is stored.',metavar="outFileName",required=True)


    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument('-c','--compare',action='store',nargs=2,dest='packageInfo',help='Compare two packages.',metavar=("Package1","Package2"))
    group.add_argument('-v','--verify',action='store',nargs=1,dest='packageName',help='Verify Content of package.',metavar='Package')
    args = parser.parse_args()

if __name__ == "__main__":
    main()

I have been troubled with this small piece of activity to be completed. I did do some experiment, but was not able to achieve the result.

Requirement:

   test2.py [-c/-v] -f

Usage or Rules:

  1. -c (compare) takes 2 parameter.

    -v (verify) takes 1 parameter.

    Either of these two must be present, but not both.

  2. -f is a mandatory parameter (output file name).

Output:

I am able to get the desired output as shown below

kp@kp:~/Study/scripts$ ./test.py -c P1 P2 -f p
kp@kp:~/Study/scripts$ ./test.py -v P1 -f p
kp@kp:~/Study/scripts$ ./test.py -v P1 
usage: test.py <functional argument> <ouput target argument>
test.py: error: argument -f/--file is required
kp@kp:~/Study/scripts$ ./test.py -c P1 P2 
usage: test.py <functional argument> <ouput target argument>
test.py: error: argument -f/--file is required
kp@kp:~/Study/scripts$ 

Problem is:

When you use, test.py -h,
1. The output will not indicate that -c/-v either of them is mandatory but not both . It indicates all the arguments are optional.
2. The output will indicate -f option under optional arguments which is incorrect. -f is mandatory argument, and I want to display outside - optional arguments.

How to change the script so that -h option output will be more user friendly (without any external validation)

usage: test.py <functional argument> <ouput target argument>

Package Compare/Verifier tool.

optional arguments:
  -h, --help            show this help message and exit
  -f outFileName, --file outFileName
                        File Name where result is stored.
  -c Package1 Package2, --compare Package1 Package2
                        Compare two packages.
  -v Package, --verify Package
                        Verify Content of package.
kiran@kiran-laptop:~/Study/scripts$ 

Code:

I am using the below code to achieve the output,

#!/usr/bin/python

import sys
import argparse

def main():
    usage='%(prog)s <functional argument> <ouput target argument>'
    description='Package Compare/Verifier tool.'
    parser = argparse.ArgumentParser(usage=usage,description=description)

    parser.add_argument('-f','--file',action='store',nargs=1,dest='outFileName',help='File Name where result is stored.',metavar="outFileName",required=True)


    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument('-c','--compare',action='store',nargs=2,dest='packageInfo',help='Compare two packages.',metavar=("Package1","Package2"))
    group.add_argument('-v','--verify',action='store',nargs=1,dest='packageName',help='Verify Content of package.',metavar='Package')
    args = parser.parse_args()

if __name__ == "__main__":
    main()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风铃鹿 2024-11-07 10:48:45

将文件名设置为位置参数,并让 argparse 设置其自己的使用消息:

$ python so.py --help
usage: so.py [-h] [-c Package1 Package2 | -v Package] outFileName

文件名应该是位置的,并且您应该让 argparse 编写其自己的使用消息。

代码

#!/usr/bin/python

import sys
import argparse

def main():
    description='Package Compare/Verifier tool.'
    parser = argparse.ArgumentParser(description=description,
                                     epilog='--compare and --verify are mutually exclusive')

    parser.add_argument('f',action='store',nargs=1,
                        help='File Name where result is stored.',
                        metavar="outFileName")

    group = parser.add_mutually_exclusive_group(required=False)
    group.add_argument('-c','--compare',action='store',nargs=2,dest='packageInfo',help='Compare two packages.',metavar=("Package1","Package2"))
    group.add_argument('-v','--verify',action='store',nargs=1,dest='packageName',help='Verify Content of package.',metavar='Package')

    args = parser.parse_args()

if __name__ == "__main__":
    main()

帮助消息

$ python so.py --help
usage: so.py [-h] [-c Package1 Package2 | -v Package] outFileName

Package Compare/Verifier tool.

positional arguments:
  outFileName           File Name where result is stored.

optional arguments:
  -h, --help            show this help message and exit
  -c Package1 Package2, --compare Package1 Package2
                        Compare two packages.
  -v Package, --verify Package
                        Verify Content of package.

--compare and --verify are mutually exclusive

Set the filename to be a positional argument, and let argparse set its own usage message:

$ python so.py --help
usage: so.py [-h] [-c Package1 Package2 | -v Package] outFileName

The filename should be positional, and you should let argparse write its own usage message.

Code

#!/usr/bin/python

import sys
import argparse

def main():
    description='Package Compare/Verifier tool.'
    parser = argparse.ArgumentParser(description=description,
                                     epilog='--compare and --verify are mutually exclusive')

    parser.add_argument('f',action='store',nargs=1,
                        help='File Name where result is stored.',
                        metavar="outFileName")

    group = parser.add_mutually_exclusive_group(required=False)
    group.add_argument('-c','--compare',action='store',nargs=2,dest='packageInfo',help='Compare two packages.',metavar=("Package1","Package2"))
    group.add_argument('-v','--verify',action='store',nargs=1,dest='packageName',help='Verify Content of package.',metavar='Package')

    args = parser.parse_args()

if __name__ == "__main__":
    main()

Help message

$ python so.py --help
usage: so.py [-h] [-c Package1 Package2 | -v Package] outFileName

Package Compare/Verifier tool.

positional arguments:
  outFileName           File Name where result is stored.

optional arguments:
  -h, --help            show this help message and exit
  -c Package1 Package2, --compare Package1 Package2
                        Compare two packages.
  -v Package, --verify Package
                        Verify Content of package.

--compare and --verify are mutually exclusive
轮廓§ 2024-11-07 10:48:45

您正在寻找什么确切的输出?我不知道有任何标准语法可以在 --help 输出中表示相互排他性,如果您编造了一种语法,可能会让您的用户感到困惑。另外,我假设 argparse 不支持它的语法(因为如果支持,它就已经可以工作了)。

我建议您保持简单,只需在每个参数的帮助中向用户解释互斥。因此,将其帮助字符串更改如下:

-c Package1 Package2, --compare Package1 Package2
                      Compare two packages (may not be used with -v).
-v Package, --verify Package
                      Verify Content of package (may not be used with -c).

这是非常明显且相当简洁的。

另一种选择是不提及它,并让用户通过尝试同时使用它们来发现它们是互斥的(argparse 自动生成一个用户友好的错误,例如“PROG: error: argument -c: not允许使用参数 -v")。

What exact output are you looking for? I am not aware of any standard syntax for denoting mutual exclusitivity in a --help output, and it would likely be confusing for your users if you made one up. Also I assume that argparse doesn't support a syntax for it (since if it did, it would already be working).

I suggest you keep it simple and just explain to your users the mutual exclusion in the help for each of the arguments. So change their help strings as follows:

-c Package1 Package2, --compare Package1 Package2
                      Compare two packages (may not be used with -v).
-v Package, --verify Package
                      Verify Content of package (may not be used with -c).

That is extremely obvious and reasonably concise.

Another alternative would be just to not mention it, and have the user discover that they are mutually exclusive by trying to use them simultaneously (argparse automatically generates a user-friendly error such as "PROG: error: argument -c: not allowed with argument -v").

染墨丶若流云 2024-11-07 10:48:45

我认为基本的抱怨是默认的位置参数和可选参数组名称。在帮助中,可选参数表示:需要像-f或--file这样的标志位置参数意味着它由位置标识。使用默认值时,positionals 确实是必需的,options 确实是可选的(不是必需的)。但用户可以使用 required 属性更改它,从而导致术语混乱。

解决这个问题的方法是定义您自己的参数组。这些组会影响帮助的布局,但对解析没有影响。它们也不会影响 usage 行。

def main():
    description='Package Compare/Verifier tool.'
    parser = argparse.ArgumentParser(usage=None,description=description)

    maingroup = parser.add_argument_group(title='required')
    maingroup.add_argument('-f','--file',nargs=1,dest='outFileName',help='File Name where result is stored.',metavar="outFileName",required=True)
    exgroup = parser.add_argument_group(title='one or the other')

    group = exgroup.add_mutually_exclusive_group(required=True)
    group.add_argument('-c','--compare',nargs=2,dest='packageInfo',help='Compare two packages.',metavar=("Package1","Package2"))
    group.add_argument('-v','--verify',nargs=1,dest='packageName',help='Verify Content of package.',metavar='Package')
    args = parser.parse_args()

产生:

usage: stack5603364.py [-h] -f outFileName (-c Package1 Package2 | -v Package)

Package Compare/Verifier tool.

optional arguments:
  -h, --help            show this help message and exit

required:
  -f outFileName, --file outFileName
                        File Name where result is stored.

one or the other:
  -c Package1 Package2, --compare Package1 Package2
                        Compare two packages.
  -v Package, --verify Package
                        Verify Content of package.

mutually_exclusive_group 仅影响 usage 行。

(-c Package1 Package2 | -v Package)

显示需要其中一个选项的组。

[-c Package1 Package2 | -v Package]

将是一个可选组。 [] 用于标记可选(在“非必需”意义上)参数。请注意 -h 是如何继续被标记的。

http://bugs.python.org/issue9694 是相关的 Python 问题,其中 argparse 作者赞成这种 argument_group 方法。

I think the basic complaint is with the default positional arguments and optional arguements group names. In the help, optional arguments means: requires a flag like -f or --file; positional arguments means it is identified by position. With default values, positionals are indeed required, and optionals are indeed optional (not required). But the user can change that with a required attribute, giving rise to confusing terminology.

A way around this is to define your own argument groups. These groups affect the layout of the help, but have no effect on parsing. They also don't affect the usage line.

def main():
    description='Package Compare/Verifier tool.'
    parser = argparse.ArgumentParser(usage=None,description=description)

    maingroup = parser.add_argument_group(title='required')
    maingroup.add_argument('-f','--file',nargs=1,dest='outFileName',help='File Name where result is stored.',metavar="outFileName",required=True)
    exgroup = parser.add_argument_group(title='one or the other')

    group = exgroup.add_mutually_exclusive_group(required=True)
    group.add_argument('-c','--compare',nargs=2,dest='packageInfo',help='Compare two packages.',metavar=("Package1","Package2"))
    group.add_argument('-v','--verify',nargs=1,dest='packageName',help='Verify Content of package.',metavar='Package')
    args = parser.parse_args()

produces:

usage: stack5603364.py [-h] -f outFileName (-c Package1 Package2 | -v Package)

Package Compare/Verifier tool.

optional arguments:
  -h, --help            show this help message and exit

required:
  -f outFileName, --file outFileName
                        File Name where result is stored.

one or the other:
  -c Package1 Package2, --compare Package1 Package2
                        Compare two packages.
  -v Package, --verify Package
                        Verify Content of package.

The mutually_exclusive_group affects only the usage line.

(-c Package1 Package2 | -v Package)

displays a group where one of the choices is required.

[-c Package1 Package2 | -v Package]

would be an optional group. [] are used to mark optional (in the 'not required' sense) arguments. Note how -h continues to be labeled.

http://bugs.python.org/issue9694 is the related Python issue, where the argparse author favors this argument_group approach.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文