不带破折号的Python可选参数与附加参数?

8 投票
2 回答
3401 浏览
提问于 2025-04-18 04:18

我想在Python中处理这样的参数格式:

script.py START | STOP | STATUS | MOVEABS <x> <y> | MOVEREL <x> <y>

换句话说,

  1. 我不想处理连字符(-);
  2. 我有多个选项,其中一个是必须的;
  3. 每个选项是互相排斥的;
  4. 有些命令(比如moveabs和moverel)需要额外的参数,但这些参数不能和其他任何参数一起出现。

这在Python中可以实现吗?我应该使用argparse还是其他什么工具?谢谢。

2 个回答

5

使用 docopt 你可以很轻松地做到这一点。

首先安装 docopt

$ pip install docopt

接下来写 script.py

"""
Usage:
    script.py (start | stop | status | moveabs <x> <y> | moverel <x> <y>)
"""
from docopt import docopt

if __name__ == "__main__":
    args = docopt(__doc__)
    print args

然后运行它:

首先显示基本的帮助信息:

$ python script.py
Usage:
    script.py (start | stop | status | moveabs <x> <y> | moverel <x> <y>)

然后尝试子命令:

开始

$ python script.py start
{'<x>': None,
 '<y>': None,
 'moveabs': False,
 'moverel': False,
 'start': True,
 'status': False,
 'stop': False}

停止

$ python script.py stop
{'<x>': None,
 '<y>': None,
 'moveabs': False,
 'moverel': False,
 'start': False,
 'status': False,
 'stop': True}

绝对移动

$ python script.py moveabs 11 22
{'<x>': '11',
 '<y>': '22',
 'moveabs': True,
 'moverel': False,
 'start': False,
 'status': False,
 'stop': False}

相对移动

$ python script.py moverel 11 22
{'<x>': '11',
 '<y>': '22',
 'moveabs': False,
 'moverel': True,
 'start': False,
 'status': False,
 'stop': False}
9

使用 add_parser 和子解析器可以解决这个问题。

import argparse
parser = argparse.ArgumentParser(prog='script.py')
sp = parser.add_subparsers(dest='cmd')
for cmd in ['START', 'STOP', 'STATUS']:
    sp.add_parser(cmd)
for cmd in ['MOVEABS', 'MOVEREL']:
    spp = sp.add_parser(cmd)
    spp.add_argument('x', type=float)
    spp.add_argument('y', type=float)
parser.print_help()
args = parser.parse_args()
print(args)

这样可以生成类似于:

2137:~/mypy$ python2.7 stack23304740.py MOVEREL -h
usage: script.py [-h] {START,STOP,STATUS,MOVEABS,MOVEREL} ...

positional arguments:
  {START,STOP,STATUS,MOVEABS,MOVEREL}

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

usage: script.py MOVEREL [-h] x y

positional arguments:
  x
  y

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

还有

2146:~/mypy$ python2.7 stack23304740.py MOVEREL 1.0 2.0
...
Namespace(cmd='MOVEREL', x=1.0, y=2.0)

以及

2147:~/mypy$ python2.7 stack23304740.py START
...
Namespace(cmd='START')

MOVEREL 的参数可以命名为 <x><y>,但这样你就得通过 args['<y>'] 来访问它们,而不是 args.y。你可以使用 metavar='<x>' 来改变显示的名称,但这并不会改变命名空间的名称。

你也可以使用 spp.add_argument('point', nargs=2, type=float)。不过不幸的是,在这种 nargs=2 的情况下有一个bug,导致我们无法使用 metavar,具体可以查看这个链接:http://bugs.python.org/issue14074

撰写回答