我试图在 Python 中使用 argparse 的 fromfile-prefix-chars 功能从文件加载我所有的命令行参数,但它一直提示我没有指定一些参数。
代码:
import argparse
def go():
parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
parser.add_argument("--option1")
parser.add_argument("--option2", type=int, required=True)
args = parser.parse_args()
if __name__ == "__main__":
go()
参数文件:
--option1 foo
--option2 1234
命令行和输出:
$ python testargparse.py @testargs
usage: testargparse.py [-h] [--option1 OPTION1] --option2 OPTION2
testargparse.py: error: argument --option2 is required
您可以看到我在文件中提供了所需的参数,但 argparse 没有看到它。
最佳答案
来自文档:
Arguments read from a file must by default be one per line ... and are treated as if they were in the same place as the original file referencing argument on the command line. So in the example above, the expression ['-f', 'foo', '@args.txt'] is considered equivalent to the expression ['-f', 'foo', '-f', 'bar'].
在例子中:
fp.write('-f\nbar')
因此文件包含:
-f
bar
换句话说,每一行文件对应命令行中的一个“单词”(空格分隔)。 --option1=foo
是一个词。 --option1 foo
被解释为就像它在命令行中被引用一样,例如。 prog.py '--option1 foo' '--option2 1234'
https://docs.python.org/dev/library/argparse.html#argparse.ArgumentParser.convert_arg_line_to_args有一个自定义函数,可以在空格上拆分行。如果您想坚持使用参数文件,请尝试一下。
import argparse
with open('args.txt', 'w') as fp:
fp.write('--option1 foo\n--option2 1234') # error
# but works with modifed 'convert...'
#fp.write('--option1=foo\n--option2=1234') # works
#fp.write('--option1\nfoo\n--option2\n1234') # works
def convert_arg_line_to_args(arg_line):
for arg in arg_line.split():
if not arg.strip():
continue
yield arg
"""
default line converter:
def convert_arg_line_to_args(self, arg_line):
return [arg_line]
"""
def go():
parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
parser.convert_arg_line_to_args = convert_arg_line_to_args
parser.add_argument("--option1")
parser.add_argument("--option2", type=int, required=True)
args = parser.parse_args(['@args.txt'])
print args
if __name__ == "__main__":
go()
@toes
建议使用shlex
解析文件。 shlex
有一个很好的功能,它去除了不必要的引号。
shlex
可用于拆分文件的各个行。
def sh_split(arg_line):
for arg in shlex.split(arg_line):
yield arg
parser.convert_arg_line_to_args = sh_split
或者它可以替换整个@file 读取方法 (_read_args_from_files
) - 这应该与 @toes
答案功能相同,除了 @file
字符串可以在命令行中的任何位置(甚至可以重复)。
def at_read_fn(arg_strings):
# expand arguments referencing files
new_arg_strings = []
for arg_string in arg_strings:
if not arg_string or not arg_string.startswith('@'):
new_arg_strings.append(arg_string)
else:
with open(arg_string[1:]) as args_file:
arg_strings = shlex.split(args_file.read())
new_arg_strings.extend(arg_strings)
return new_arg_strings
parser._read_args_from_files = at_read_fn
显然,更干净的生产版本会在 ArgumentParser
子类中修改这些方法。
关于python - 为什么 Python argparse 中的 fromfile-prefix-chars 不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25084993/