如何让 argparse 识别跟随可变长度可选参数的位置参数?

Posted

技术标签:

【中文标题】如何让 argparse 识别跟随可变长度可选参数的位置参数?【英文标题】:How can I get argparse to recognize a positional argument which follows a variable length optional argument? 【发布时间】:2020-03-14 03:57:39 【问题描述】:

我正在编写一个脚本,用于合并多个输入文件,生成一个输出文件,并且我想使用argparse 构建一个小型命令行界面。对我来说,最自然的方法是使用单个可选输入 -i,它接受一个或多个输入文件名,后跟一个位置参数,表示输出文件名。这是我想到的一个例子:

#!/usr/bin/env python3
"""
Script for merging input files
"""
import argparse

script_docstring = 'Read some input files and create a merged output.'
parser = argparse.ArgumentParser(description=script_docstring)
# Optional input file names
parser.add_argument('-i --inputs', nargs='+', type=str, required=True,
                    help='Input file names', dest='inputs')
# Positional output file name
parser.add_argument('fname_out', type=str, help='Output file name')
args = parser.parse_args()

# Display what the user chose at the command line
print(args.inputs)
print(args.fname_out)

当我打印由 argparse 创建的自动生成的帮助消息时,调用签名看起来像我想要的那样:

> ./mergefiles.py --help
usage: mergefiles.py [-h] -i --inputs INPUTS [INPUTS ...] fname_out

Read some input files and create a merged output.

positional arguments:
  fname_out             Output file name

optional arguments:
  -h, --help            show this help message and exit
  -i --inputs INPUTS [INPUTS ...]
                        Input file names

但是,当我实际尝试运行脚本时,它给出了一个错误,提示我 argparse 错误地解析了最终的位置参数,就好像它被包含在选项列表中一样:

> ./mergefiles.py -i a.in b.in c.in test.out
usage: mergefiles.py [-h] -i --inputs INPUTS [INPUTS ...] fname_out
mergefiles.py: error: the following arguments are required: fname_out

我的问题: 是否有可能让argparse 正确处理这样的情况,将最终参数视为位置参数?或者是我接受“解决方法”解决方案的唯一选择,例如将输出文件名也转换为可选参数,例如-f --fname_out 或类似的。

如果无法做我想做的事,那么我计划将其作为我的后备解决方案来实施。然而,在我接受一个不优雅的解决方法之前,我很好奇是否真的有可能让argparse 以“正确”的方式处理这个问题。

【问题讨论】:

不,你不能欺骗argparse 来处理这个问题。由于+inputs 获得了所有剩余的字符串,fname_out 没有留下任何字符串。理想情况下,它应该做某种“前瞻”并为位置保留一个,但当前代码没有这样做。首先放置位置字符串应该有效:'test.out -i a b c' 是的,某种类型的前瞻功能(我想这类似于某些regular expression engines 中存在的功能)是我想到的。感谢您确认它没有实现,因此没有触发它的秘密技术。 【参考方案1】:

当使用位置作为最后一个参数时,您必须使用 -- 来分隔参数:

python3 args.py -i infile1 infile2 -- outfile
['infile1', 'infile2']
outfile

希望对你有帮助

【讨论】:

谢谢——这确实像宣传的那样有效,而且用于分隔参数的双破折号输入技术(“--”)是我不知道的,所以是的,它很有帮助。但是,我也将此解决方案归类为一种解决方法,只是一种不同的类型。 @stachyra :双破折号-- 不是一种解决方法,它是一个功能:-) man bash 表示它表示选项的结束,并且在它之后只允许位置参数。参见例如unix.stackexchange.com/a/187548/266189.

以上是关于如何让 argparse 识别跟随可变长度可选参数的位置参数?的主要内容,如果未能解决你的问题,请参考以下文章

Argparse:“可选参数”下列出的必需参数?

如何在 argparse 中使用带有 nargs='*' 参数的可选位置参数?

Python 2.7 argparse:如何正确嵌套可选的互斥参数?

Python argparse 可选 arg 需要其他参数

python argparse - 要么两个可选参数,要么一个都没有

Argparse 无法识别参数