首页 > 解决方案 > Python Argparse:使用单个大头钉作为标志,例如 `./myscript -5`,如 Git 和 CoreUtils

问题描述

在 Python Argparse 中使用 single-tack-作为标志

许多 GNU CoreUtils ( head, tail, 等) 和 Git 都有一个命令行特性,允许你做例如

$ head -5 ...
$ tail -20 ...
$ git log -5 ...

如何使用 Python 的argparse模块达到同样的效果?

示例解析器

#!/usr/bin/env python3
import argparse
p = argparse.ArgumentParser()
p.add_argument('-', dest='dash', help='Tell me how many!')
p.add_argument('-n', dest='n', help='This works, but I dislike it!')
p.add_argument('positional', nargs='*')
print(p.parse_intermixed_args())

这会生成用法:

$ ./example.py --help
usage: example.py [-h] [- DASH] [-n N] [positional [positional ...]]

什么有效

使用 eg -n5-n=5-n 5all 可以按预期工作。

$ ./example.py before -n5 after
Namespace(dash=None, n='5', positional=['before', 'after'])

$ ./example.py before -n=5 after
Namespace(dash=None, n='5', positional=['before', 'after'])

$ ./example.py before -n 5 after
Namespace(dash=None, n='5', positional=['before', 'after'])

什么不能按预期工作

在这里,我们可以看到它-5没有按预期工作。令人惊讶的是,- 5确实有效。

下面的第一个示例是我想要的用法,但结果不是我想要的。

# This does not work, `-5` is considered a positional argument.
# ~~ THIS IS WHAAT I WANT TO HAVE WORK! ~~
$ ./example.py before -5 after
Namespace(dash=None, n=None, positional=['before', '-5', 'after'])

# This works, but is not what I want
$ ./example.py before - 5 after
Namespace(dash='5', n=None, positional=['before', 'after'])

标签: pythonpython-3.xcommand-lineargparse

解决方案


如记录在

parser.add_argument('-f', '--foo')

'-f' 是一个短选项,'--foo' 是一个长选项。

(首先) Long 用于dest, 并且可以用作 '--foo=value'。Short 可以用作“-fvalue”或带有“store_true”短的“-bf5”。

但是这种用法是如何使用标志的结果。没有坚持精确语法的前置过滤器。'-f=value' 应该可以工作,'-foobar' 可以用作 long。

您的 '-' 不符合此记录的模式,并且不能保证无论长短都可以正常工作。

In [1]: import argparse
In [2]: parser=argparse.ArgumentParser()
In [3]: a = parser.add_argument('-','-f','--foo')

In [5]: parser.parse_args(['--foo=5'])
Out[5]: Namespace(foo='5')
In [6]: parser.parse_args(['-f5'])
Out[6]: Namespace(foo='5')
In [7]: parser.parse_args(['-5'])
usage: ipython3 [-h] [- FOO]
ipython3: error: unrecognized arguments: -5
     ...
In [8]: parser.parse_args(['-=5'])
Out[8]: Namespace(foo='5')

看起来 '-' 的处理方式很长。它不能用作短路。

通常argparse是 POSIX getopt 实践的扩展,但并非所有 Linux 实用程序都使用它(尤其是在 UNIX 开发早期创建的那些)。


推荐阅读