Tom*_*nen 4 python python-2.7 argparse
我试图在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()
Run Code Online (Sandbox Code Playgroud)
参数文件:
--option1 foo
--option2 1234
Run Code Online (Sandbox Code Playgroud)
命令行和输出:
$ python testargparse.py @testargs
usage: testargparse.py [-h] [--option1 OPTION1] --option2 OPTION2
testargparse.py: error: argument --option2 is required
Run Code Online (Sandbox Code Playgroud)
你可以看到我在文件中提供了必需的参数,但是argparse没有看到它.
从文档:
从文件读取的参数默认情况下必须是每行一个...并且被视为与命令行上的原始文件引用参数位于同一位置.所以在上面的例子中,表达式['-f','foo','@ args.txt']被认为等同于表达式['-f','foo',' - f','bar'] .
在示例中:
fp.write('-f\nbar')
Run Code Online (Sandbox Code Playgroud)
所以该文件包含:
-f
bar
Run Code Online (Sandbox Code Playgroud)
换句话说,每个文件行对应于命令行中的一个"字"(空白分隔). --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()
Run Code Online (Sandbox Code Playgroud)
@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
Run Code Online (Sandbox Code Playgroud)
或者它可以替换整个@file读取方法(_read_args_from_files) - 这应该与@toesanswer 相同,除了@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
Run Code Online (Sandbox Code Playgroud)
显然,更清洁的生产版本会在ArgumentParser子类中修改这些方法.
问题是,当在文件中指定时,每个参数必须在它和选项名称之间有一个“=”。虽然从命令行运行时 argparse 在该格式上更加灵活(其中空格或 = 可以),但从文件运行时它必须有一个“=”。
因此,一个有效的参数文件将是:
--option1=foo
--option2=1234
Run Code Online (Sandbox Code Playgroud)
还有一些需要注意的事情,请确保在行尾没有任何额外的空格,否则当 argparse 读取文件时,该选项将包含空格。
| 归档时间: |
|
| 查看次数: |
2237 次 |
| 最近记录: |