python - 为什么 Python argparse 中的 fromfile-prefix-chars 不起作用?

标签 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()

参数文件:

--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/

相关文章:

python - 如何在 Vim 中通过 ALE 运行 isort?

python - 如何向 distutils 添加 C 编译器选项

python - 如何使用过滤函数修复数组 bool 错误

python - 当用于测试序列(列表、元组、字符串等)是否包含值时,关键字 "in"的真正作用是什么。循环直到找到值?

python - argparse 其他参数隐含的子解析器

来自无限集合的 Python argparse 选择

python - 如何附加此列表?

python - 在 Python 中使用 matplotlib 绘图时出现意外响应

Python argparse 错误

python-2.7 - imshow 一个灰度图像和一个二进制图像 python