我想在Python中使用argparse
来声明参数如下:
./get_efms_by_ids [-h] [-v] [inputfile [1 3 4 9] [-c 11..18] [20 25 40]]
在这种情况下我想做的是:
如果使用inputfile
,则可以使用两种类型的可选参数:1 3 4 9
或c 11..18
或两者。如果我不输入inputfile
,则必须缺少可选参数。
例如: 我可以向您展示命令行使用的一些示例:
./get_efms_by_ids Vacf.txt // default: get 1 or 10 first lines in Vacf.txt
./get_efms_by_ids Vacf.txt 1 3 4 9 // get the lines that indexes: 1 3 4 9 in Vacf.txt
./get_efms_by_ids Vacf.txt c 11..18 22 25 29 // get the lines that indexes are from 11 to 18, then the lines 22, 25, 29
./get_efms_by_ids c 11.. 18 // shows a readable error message
./get_efms_by_ids 1 3 4 9 // shows a readable error message
可以在以下示例中使用args='?'
或args='*'
:
parser = argparse.ArgumentParser(description='Selecting some Elementary Flux Modes by indexes.',version='1.0')
parser.add_argument('efm_matrix_file', type=file, help='give the name of the efms matrix file')
parser.add_argument('ids', nargs='?', help='give the indexes of the chosen efms')
parser.add_argument('-i','--indexes',nargs='*', help='give the begin and start indexes of the chosen efms')
但结果并不符合本文开头提出的目的。
任何帮助将不胜感激。
答案 0 :(得分:3)
首先,我会放弃-c
选项。您不需要-c
和..
来表示一系列值。这样可以简化您对
./get_efms_by_ids [-h] [-v] [inputfile [index ...]]
其中每个index
可以是单个整数,也可以是lower..upper
指定的范围。
参数解析器可以是一个简单的
def index_type(s):
try:
return int(s)
except ValueError:
try:
return map(int, s.split(".."))
except:
raise ArgumentTypeError("Invalid index: %s" % (s,))
p = ArgumentParser()
p.add_argument("-h")
p.add_argument("-v")
p.add_argument("inputfile", nargs="?")
p.add_argument("indices", nargs="*", type=index_type)
args = p.parse_args()
if not (args.inputfile is None or os.path.exists(args.inputfile)):
sys.exit("Invalid file name: %s" % (args.inputfile,))
在解析之后,您必须检查第一个位置参数(如果有)是否是有效文件,因为任何字符串可以是有效的文件名。
index_type
函数只是在解析过程中如何转换每个索引(无论是整数还是范围)的一个示例。
答案 1 :(得分:1)
我采取了与chepner不同的方法,但借用了一些chepner的想法:放弃-c
选项并使用修改后的index_type()
。
#!/usr/bin/env python
import argparse
from itertools import chain
def index_type(s):
try:
return [int(s)]
except ValueError:
try:
start, stop = map(int, s.split('..'))
return range(start, stop + 1)
except:
raise argparse.ArgumentTypeError("Invalid index: %s" % (s,))
def get_options():
parser = argparse.ArgumentParser()
parser.add_argument('-v')
parser.set_defaults(fileinput=None)
options, remaining = parser.parse_known_args()
if remaining:
parser = argparse.ArgumentParser()
parser.add_argument('fileinput', type=argparse.FileType())
parser.add_argument('selected_lines', nargs='*', type=index_type)
parser.parse_args(remaining, namespace=options)
# Convert a nested list into a set of line numbers
options.selected_lines = set(chain.from_iterable(options.selected_lines))
# If the command line does not specify the line numbers, assume a default
if not options.selected_lines:
options.selected_lines = set(index_type('1..10'))
return options
if __name__ == '__main__':
options = get_options()
# If the command line contains a file name, loop through the file and process only the lines
# requested
if options.fileinput is not None:
for line_number, line in enumerate(options.fileinput, 1):
if line_number in options.selected_lines:
line = line.rstrip()
print '{:>4} {}'.format(line_number, line)
-v
标志。对于第一次解析,我使用parse_known_args()
方法,忽略那些它不理解的参数。 "11..18 1 3 4 9"
之类的内容转换为[1, 3, 4, 9, 11, 12, 13, 14, 15, 16, 17, 18]
index_type()
(感谢chepner),我能够将命令行从"11..18 1 3 4 9"
解析为[11, 12, 13, 14, 15, 16, 17, 18], [1], [3], [4], [9]]
1..10
get_options
返回后,options.fileinput
将为None
或文件句柄 - 无需打开要读取的文件。 options.selected_lines
将是一组要选择的行号