Argparse 可选的位置参数?
我有一个脚本,应该这样使用:
usage: installer.py dir [-h] [-v]
dir
是一个位置参数,定义方式如下:
parser.add_argument('dir', default=os.getcwd())
我希望 dir
是可选的:当没有指定时,它应该默认为 cwd
。
不幸的是,当我不指定 dir
参数时,我会收到 Error: Too few arguments
的错误信息。
4 个回答
简短回答
正如之前的两个回答所示,你可以使用 nargs='?'
来接受一个可选的位置参数。如果你想的话,也可以直接把这个参数变成 Path
类型,或者把当前工作目录缩短为 .
。
myfile.py
import argparse
import pathlib
parser = argparse.ArgumentParser()
parser.add_argument("dir", nargs="?", default=".", type=pathlib.Path)
parsed_args = parser.parse_args()
print("Installing to", parsed_args.dir.resolve())
$ python myfile.py
Installing to /users/myname/myfolder
$ python myfile.py /usr/bin/
Installing to /usr/bin
详细回答
因为你在问题中提到了像 -h
和 -v
这样的标志选项,所以这些例子可能会对你有帮助:
标志(例如 -v
)
我们可以把那些不需要参数的可选选项称为“标志”。对于标志,我们只关心它们是否被提供。-h
是 argparse 自动添加的标志(还有更长的版本 --help
),所以我们不应该去覆盖它。如果我们考虑 -v
的话,
myfile.py
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--version",
action="store_true")
parsed_args = parser.parse_args()
if parsed_args.version:
print("version flag given")
else:
print("version flag not given")
注意,add_argument()
的第二个参数是这个选项的更长名称。虽然这不是强制的,但它确实让后面的代码更易读(比如 parsed_args.version
比 parsed_args.v
更清晰),也让你调用安装程序时更明确。
$ python myfile.py -v
version flag given
$ python myfile.py --version
version flag given
$ python myfile.py
version flag not given
可选参数(例如 --installdir /usr/bin/
)
可以说,在你的情况下,使用可选参数会比使用位置参数更好。
myfile.py
import argparse
import pathlib
parser = argparse.ArgumentParser()
parser.add_argument(
"-i",
"--installdir", # Optional (but recommended) long version
type=pathlib.Path,
default="/bin"
)
parsed_args = parser.parse_args()
print("Installing to", parsed_args.installdir)
$ python myfile.py -i /usr/bin/
Installing to /usr/bin
$ python myfile.py --installdir /usr/bin/
Installing to /usr/bin
$ python myfile.py
Installing to /bin
这是对@VinaySajip回答的补充。这里有一些额外的 nargs
选项值得一提。
parser.add_argument('dir', nargs=1, default=os.getcwd())
N(一个整数)。从命令行获取N个参数,这些参数会被放到一个列表里。
parser.add_argument('dir', nargs='*', default=os.getcwd())
'*'。所有在命令行中出现的参数都会被放到一个列表里。注意,通常来说,使用 nargs='*'
时,多个位置参数是没有太大意义的,但多个可选参数是可以的。
parser.add_argument('dir', nargs='+', default=os.getcwd())
'+'。和'*'一样,所有在命令行中出现的参数都会被放到一个列表里。不过,如果没有至少一个命令行参数,就会出现错误信息。
parser.add_argument('dir', nargs=argparse.REMAINDER, default=os.getcwd())
argparse.REMAINDER
。所有剩下的命令行参数都会被放到一个列表里。这通常对那些需要调用其他命令行工具的命令行工具很有用。
如果没有提供 nargs
这个参数,消耗的参数数量会根据动作来决定。一般来说,这意味着会消耗一个命令行参数,并产生一个单独的项目(而不是列表)。
编辑(摘自@Acumenus的评论) nargs='?'
文档中说:'?'。如果可能的话,会从命令行消耗一个参数,并作为单独的项目返回。如果没有命令行参数,默认值会被返回。
使用 nargs='?'
(如果你需要多个目录,可以用 nargs='*'
)
parser.add_argument('dir', nargs='?', default=os.getcwd())
扩展示例:
>>> import os, argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('-v', action='store_true')
_StoreTrueAction(option_strings=['-v'], dest='v', nargs=0, const=True, default=False, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('dir', nargs='?', default=os.getcwd())
_StoreAction(option_strings=[], dest='dir', nargs='?', const=None, default='/home/vinay', type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args('somedir -v'.split())
Namespace(dir='somedir', v=True)
>>> parser.parse_args('-v'.split())
Namespace(dir='/home/vinay', v=True)
>>> parser.parse_args(''.split())
Namespace(dir='/home/vinay', v=False)
>>> parser.parse_args(['somedir'])
Namespace(dir='somedir', v=False)
>>> parser.parse_args('somedir -h -v'.split())
usage: [-h] [-v] [dir]
positional arguments:
dir
optional arguments:
-h, --help show this help message and exit
-v