如何使用 nargs='+' 解析多个位置参数
How to parse several positional arguments with nargs='+'
以下是我要实现的目标的简短摘要:
- 获取一个或多个(表格)文件
- 寻找一个特定的字符串键(目前只有一个键,但我可以想象扩展它以接受多个键)
- 与键匹配的行,提取给定位置或位置范围内的字符。
所以在一个理想的世界里,我想 运行 我的脚本通过以下方式,它们都是有效的用例:
python myscript.py file1 file2 file3 "key" 10
python myscript.py file1 file2 "key" 10 12
python myscript.py file1 "key" 10 12
python myscript.py file1 "key" 10
鉴于我尝试过的用例:
parser = argparse.ArgumentParser()
parser.add_argument("files", nargs='+', help="input files")
parser.add_argument("gene", help="gene of interest")
parser.add_argument("pos", nargs='+', type=int, help="position(s) to analyze")
""" Validate pos """
if len(args.pos) > 2:
sys.exit("Positions argument needs to be a single integer or two integers denoting a range!")
...
# in some other function
if len(args.pos) == 1:
key = row[SIND][args.pos[0]]
elif len(args.pos) == 2:
key = row[SIND][args.pos[0] : args.pos[1]]
else:
print(args.pos, len(args.pos))
sys.exit("args.pos assertion failed!")
当只有一个整数时有效,但当我发送两个整数来分析一个范围时无效。在后一种情况下,"key" 也被解释为一个文件,因此我得到 FileNotFoundError: [Errno 2] No such file or directory: 'IGHV4-39'
.
问题 1: 是否可以标记或指示位置参数,以便我可以在 files
参数结束和 gene
开始时告诉 argparse?我不想让它们成为可选参数,因为如果省略三个参数中的任何一个,脚本的逻辑就不完整。
问题2:将pos参数一分为二是否有用; pos 接受一个整数,range 接受两个整数,然后让它们互斥?
有什么想法吗?
问题 1 的答案
"Is it possible to flag ... positional arguments?" 好吧,如果你这样做了,那么它们就不再是位置参数了!因为毕竟所有位置参数都是通过位置来定义的,而不是通过标记来定义的。
我认为您真正需要的只是 required
选项,而不是尝试使用位置参数太聪明。您的目标是创建一个非常聪明的界面,无论输入如何都能神奇地计算出您想要的内容,还是一个可以预测地工作并产生良好错误消息的界面?
我可以在这一点上讽刺一下,因为我过去花了太多时间做第一个而不是只做第二个。
那为什么不呢:
test.py
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--files', required=True, nargs='+')
parser.add_argument('--genes', required=True, nargs='+')
parser.add_argument(
'--pos', required=True, nargs='+', type=int, help="position(s) to analyze")
opts = parser.parse_args()
print(dir(parser))
print('files: %s, genes: %s, poses: %s' % (
opts.files, opts.genes, opts.pos))
所以:
$ python test.py
usage: test.py [-h] --files FILES [FILES ...] --genes GENES [GENES ...] --pos
POS [POS ...]
test.py: error: the following arguments are required: --files, --genes, --pos
$ python test.py --files file1 file2 --genes xzy --pos 2 1
files: ['file1', 'file2'], genes: ['xzy'], poses: [2, 1]
问题 2 的答案
你本质上不是在问 "what is the best interface here" 吗?当然,这是您需要决定的事情。我的建议:保持简单。为什么不这样做:
parser.add_argument('--start', '-s', required=True, nargs=1, type=int)
parser.add_argument('--end', '-e', nargs=1, type=int)
opts = parser.parse_args()
if opts.end is None:
opts.end = opts.start + 1
这是 sys.argv
解析的快速实现:
In [97]: txt='file1 file2 file3 "key" 10 12'
In [98]: argv=txt.split()
In [99]: argv
Out[99]: ['file1', 'file2', 'file3', '"key"', '10', '12']
In [104]: files,rows,key=[],[],None
In [105]: for a in argv[::-1]:
...: try:
...: rows.append(int(a))
...: except ValueError:
...: if key is None: key=a
...: else: files.append(a)
...:
In [106]: files
Out[106]: ['file3', 'file2', 'file1']
In [107]: rows
Out[107]: [12, 10]
In [108]: key
Out[108]: '"key"'
您甚至可以使用 parse_known_args
来处理其他标记的参数,并应用此逻辑来解析 extras
。
argparse
从左到右处理参数;您的位置逻辑更适合相反。标志 (optionals
) 在参数字符串之间提供明确定义的分隔符。没有它们,解析多个 +
参数是不可能的。第一个 '+' 是贪婪的(想想 regex
行为),并抓住所有。并且在将字符串分配给参数时,它不会检查类型。类型转换(例如到 int
)发生在字符串分配之后。
以下是我要实现的目标的简短摘要:
- 获取一个或多个(表格)文件
- 寻找一个特定的字符串键(目前只有一个键,但我可以想象扩展它以接受多个键)
- 与键匹配的行,提取给定位置或位置范围内的字符。
所以在一个理想的世界里,我想 运行 我的脚本通过以下方式,它们都是有效的用例:
python myscript.py file1 file2 file3 "key" 10
python myscript.py file1 file2 "key" 10 12
python myscript.py file1 "key" 10 12
python myscript.py file1 "key" 10
鉴于我尝试过的用例:
parser = argparse.ArgumentParser()
parser.add_argument("files", nargs='+', help="input files")
parser.add_argument("gene", help="gene of interest")
parser.add_argument("pos", nargs='+', type=int, help="position(s) to analyze")
""" Validate pos """
if len(args.pos) > 2:
sys.exit("Positions argument needs to be a single integer or two integers denoting a range!")
...
# in some other function
if len(args.pos) == 1:
key = row[SIND][args.pos[0]]
elif len(args.pos) == 2:
key = row[SIND][args.pos[0] : args.pos[1]]
else:
print(args.pos, len(args.pos))
sys.exit("args.pos assertion failed!")
当只有一个整数时有效,但当我发送两个整数来分析一个范围时无效。在后一种情况下,"key" 也被解释为一个文件,因此我得到 FileNotFoundError: [Errno 2] No such file or directory: 'IGHV4-39'
.
问题 1: 是否可以标记或指示位置参数,以便我可以在 files
参数结束和 gene
开始时告诉 argparse?我不想让它们成为可选参数,因为如果省略三个参数中的任何一个,脚本的逻辑就不完整。
问题2:将pos参数一分为二是否有用; pos 接受一个整数,range 接受两个整数,然后让它们互斥?
有什么想法吗?
问题 1 的答案
"Is it possible to flag ... positional arguments?" 好吧,如果你这样做了,那么它们就不再是位置参数了!因为毕竟所有位置参数都是通过位置来定义的,而不是通过标记来定义的。
我认为您真正需要的只是 required
选项,而不是尝试使用位置参数太聪明。您的目标是创建一个非常聪明的界面,无论输入如何都能神奇地计算出您想要的内容,还是一个可以预测地工作并产生良好错误消息的界面?
我可以在这一点上讽刺一下,因为我过去花了太多时间做第一个而不是只做第二个。
那为什么不呢:
test.py
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--files', required=True, nargs='+')
parser.add_argument('--genes', required=True, nargs='+')
parser.add_argument(
'--pos', required=True, nargs='+', type=int, help="position(s) to analyze")
opts = parser.parse_args()
print(dir(parser))
print('files: %s, genes: %s, poses: %s' % (
opts.files, opts.genes, opts.pos))
所以:
$ python test.py
usage: test.py [-h] --files FILES [FILES ...] --genes GENES [GENES ...] --pos
POS [POS ...]
test.py: error: the following arguments are required: --files, --genes, --pos
$ python test.py --files file1 file2 --genes xzy --pos 2 1
files: ['file1', 'file2'], genes: ['xzy'], poses: [2, 1]
问题 2 的答案
你本质上不是在问 "what is the best interface here" 吗?当然,这是您需要决定的事情。我的建议:保持简单。为什么不这样做:
parser.add_argument('--start', '-s', required=True, nargs=1, type=int)
parser.add_argument('--end', '-e', nargs=1, type=int)
opts = parser.parse_args()
if opts.end is None:
opts.end = opts.start + 1
这是 sys.argv
解析的快速实现:
In [97]: txt='file1 file2 file3 "key" 10 12'
In [98]: argv=txt.split()
In [99]: argv
Out[99]: ['file1', 'file2', 'file3', '"key"', '10', '12']
In [104]: files,rows,key=[],[],None
In [105]: for a in argv[::-1]:
...: try:
...: rows.append(int(a))
...: except ValueError:
...: if key is None: key=a
...: else: files.append(a)
...:
In [106]: files
Out[106]: ['file3', 'file2', 'file1']
In [107]: rows
Out[107]: [12, 10]
In [108]: key
Out[108]: '"key"'
您甚至可以使用 parse_known_args
来处理其他标记的参数,并应用此逻辑来解析 extras
。
argparse
从左到右处理参数;您的位置逻辑更适合相反。标志 (optionals
) 在参数字符串之间提供明确定义的分隔符。没有它们,解析多个 +
参数是不可能的。第一个 '+' 是贪婪的(想想 regex
行为),并抓住所有。并且在将字符串分配给参数时,它不会检查类型。类型转换(例如到 int
)发生在字符串分配之后。