如何跳过 Python Argparse 中的位置参数

How to skip a positional argument in Python Argparse

我使用 argparse 来解析我的脚本的参数。现在我想编写一个程序,其中 运行 是一个特定的工具,如果第一个参数(在程序名称之后)是工具的名称(在 class 中关闭)。例如,如果我想 运行 我必须输入的“计数器”工具:

python myscript.py counter filename

而如果我想 运行“fasta2bed”,我必须输入:

python myscript.py fasta2bed filename

我写了这段代码,但似乎你不能用 Argparse 跳过位置参数:

import argparse

parser=argparse.ArgumentParser(
    usage="""python myscript.py {toolname} filename [-option]""",
    description='''Description.''',
    epilog="""Epilog.""")
parser.add_argument('counter', nargs='?', choices=['counter'],        help='count how many features are in the input file [-l][-s]')
parser.add_argument('fasta2bed', nargs='?', choices=['fasta2bed'],    help='read sequences in FASTA format and print out BED format')
parser.add_argument('filename', help='the input file name')
parser.add_argument('-l', '--long', action='store_true', help='retrive a    long summary file (default)')
parser.add_argument('-s', '--short', action='store_true', help='retrive a    short summary file')
args=parser.parse_args()

问题是当我尝试 运行 python myscript.py fasta2bed filename 时它不起作用,因为它需要 counter.

所以我尝试像这样将所有内容插入一个参数中:

parser.add_argument('tool', nargs='?', choices=['counter', 'fasta2bed'], help='help')

以此为目标:

data = open("inputfile", "r")

if args.tool == "counter":
    counter(data).summarize()      #summarize is a function present in the counter class
elif args.tool == "fasta2bed":
    fasta2bed(data)                #fasta2bed is just a function

但它不起作用,因为它 运行s counter 而不是 fasta2bed...

我怎样才能完成这项工作?

它可以使用类似的东西吗:

parser.add_argument('--counter', action='store_true', default=False)
parser.add_argument('--fasta2bed', action='store_true', default=False)

还要在 python 中检查脚本后的直接参数,您可以使用:

import sys

filename, methodname = sys.argv

现在您将第一个参数传递给脚本 methodname

在您的脚本副本中包含此行

parser.add_argument('tool', choices=['counter', 'fasta2bed'], help='help')

print(args)

我得到了想要的行为

0827:~/mypy$ python stack33480471.py counter filename
Namespace(filename='filename', long=False, short=False, tool='counter')
0828:~/mypy$ python stack33480471.py fasta2bed filename
Namespace(filename='filename', long=False, short=False, tool='fasta2bed')
0828:~/mypy$ python stack33480471.py tool filename
usage: python myscript.py {toolname} filename [-option]
stack33480471.py: error: argument tool: invalid choice: 'tool' (choose from 'counter', 'fasta2bed')

请注意,我删除了 nargs='?'。这样解析更清晰,更可预测。我只是显示 args。在迷失测试特定值之前,您需要清楚地了解生成的命名空间是什么样的。如果用户没有选择,会发生什么?

其他人可能会建议使用子解析器。我认为这是一个经常引起更多混乱的高级工具。

store_true 选项的使用也是一个好主意。但它需要使用'--counter'而不是'counter'。那还不错,只是不同而已。

据我所知,你不能按照你想要的方式跳过争论。就是说,您似乎真的不想跳过一个。做到这一点的方法是改变你看待问题的方式。可行的是有一个接受 'counter' 或 'fasta2bed' 的参数。更改代码中的相关行可能会产生如下内容:

import argparse
parser=argparse.ArgumentParser(
    usage="""python myscript.py {toolname} filename [-option]""",
    description='''Description.''',
    epilog="""Epilog.""")
parser.add_argument('toolname', choices=['counter', 'fasta2bed'], help='the name of the tool to be used')
parser.add_argument('filename', help='the input file name')
parser.add_argument('-l', '--long', action='store_true',     help='retrive a long summary file (default)')
parser.add_argument('-s', '--short', action='store_true', help='retrive a short summary file')
args=parser.parse_args()

希望这能帮助您入门。

编辑额外 material:

您可以通过检查 args.toolname:

来检查工具名称的选择
if args.toolname == 'counter':
    print 'Running counter'
else:
    print 'Running fasta2bed'

请注意,如果您有超过 2 个选择,则需要使用 elif