【问题标题】:Dynamic arguments for Python's argparsePython argparse 的动态参数
【发布时间】:2021-05-06 11:00:23
【问题描述】:

我需要在 Python 中动态创建参数列表。我创建了一个脚本来演示这一点,名为 args.py,如下所示:

#!/usr/bin/python
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-args_file', default = 'args.txt')

with open(parser.parse_args().args_file, 'r') as f:
    args = f.readlines()

for arg in args:
    parser.add_argument('-' + arg.strip())

dynamic_args = parser.parse_args()

print dynamic_args

我在同一个文件夹中还有一个文本文件,名为 args.txt,如下所示:

arg1
arg2
arg3

正如预期的那样,不带参数运行 args.py 会导致:

Namespace(arg1=None, arg2=None, arg3=None, args_file='args.txt')

但是,我遇到的问题是使用 -h 参数运行我的脚本。我希望帮助显示在 args_file 中找到的参数,如下例所示:

usage: args.py [-h] [-args_file ARGS_FILE] [-arg1 ARG1] [-arg2 ARG2]
               [-arg3 ARG3]

我看到的是:

usage: args.py [-h] [-args_file ARGS_FILE]

此外,如果我以交互方式运行脚本(即 python -i arg.py),并在交互提示符下键入命令“parser.print_usage()”,我会得到想要的响应(显示 -argN 参数)。此外,键入“arg.py -arg1 1”或“arg.py arg1 1”会导致“无法识别的参数”。

我已经尝试了所有我能想到的方法,但到目前为止我都没有成功。有没有 Python 爱好者有什么建议?

【问题讨论】:

  • 您看到的帮助消息打印在first parse_args(),其他选项尚未设置。
  • 您需要在第一次 parse_args() 调用期间禁止传递 -h..
  • 附带说明,您不需要先执行args = f.readlines(),然后再执行for arg in args:f 已经是一个可迭代的行;只需执行for arg in f: 即可获得相同的结果(但更简单、更简洁、更高效)。
  • 我在下面找到了解决方案。感谢您的帮助,也感谢旁注。我也实现了。

标签: python python-2.7


【解决方案1】:

正如 Martjin 指出的那样,您可以在第一次忽略解析器的帮助。另一件事是第一次使用parse_known_args,所以你只解析args_file。

在这种情况下,我喜欢在第一次解析时使用一次性解析器,在最终解析时使用完整解析器来保持清晰:

import argparse
argfile_parser = argparse.ArgumentParser(add_help=False)
full_parser = argparse.ArgumentParser()
argfile_parser.add_argument('-args_file', default = 'args.txt')
full_parser.add_argument('-args_file', default = 'args.txt')
with open(argfile_parser.parse_known_args()[0].args_file, 'r') as f:
    for arg in f:
        full_parser.add_argument('-' + arg.strip())

dynamic_args = full_parser.parse_args()

print dynamic_args

为了测试,我添加了一个文件args2.txt

argA
argB
argC

我认为结果就是您想要的:

lap:~$ python tmp.py -h
usage: tmp.py [-h] [-args_file ARGS_FILE] [-arg1 ARG1] [-arg2 ARG2]
              [-arg3 ARG3]

optional arguments:
  -h, --help            show this help message and exit
  -args_file ARGS_FILE
  -arg1 ARG1
  -arg2 ARG2
  -arg3 ARG3
lap:~$ python tmp.py -args_file args2.txt
Namespace(argA=None, argB=None, argC=None, args_file='args2.txt')
lap:~$ python tmp.py -h -args_file args2.txt
usage: tmp.py [-h] [-args_file ARGS_FILE] [-argA ARGA] [-argB ARGB]
              [-argC ARGC]

optional arguments:
  -h, --help            show this help message and exit
  -args_file ARGS_FILE
  -argA ARGA
  -argB ARGB
  -argC ARGC
lap:~$ python tmp.py -arg1 foo
Namespace(arg1='foo', arg2=None, arg3=None, args_file='args.txt')
lap:~$ python tmp.py -args_file args2.txt -argA bar
Namespace(argA='bar', argB=None, argC=None, args_file='args2.txt')

【讨论】:

  • 这正是我所需要的!我尝试了 add_help=False、多个 ArgumentParser 对象和 parse_known_args 的不同组合,但我似乎无法连接所有点。谢谢!
  • 你将如何“访问”动态参数,比如如果我只有一个字符串列表,我如何从 argparse 输出中“查找”一个参数?
  • nvm getattr(script_args, 'arg_name')
【解决方案2】:

根据 Hazen 的回答,使用 parents 选项会更容易。

https://docs.python.org/3/library/argparse.html#parents

import argparse
argfile_parser = argparse.ArgumentParser(add_help=False)
argfile_parser.add_argument('-args_file', default = 'args.txt')
full_parser = argparse.ArgumentParser(parents=[argfile_parser])
with open(argfile_parser.parse_known_args()[0].args_file, 'r') as f:
    for arg in f:
        full_parser.add_argument('-' + arg.strip())

dynamic_args = full_parser.parse_args()

print dynamic_args

【讨论】:

    猜你喜欢
    • 2014-07-23
    • 1970-01-01
    • 1970-01-01
    • 2018-07-09
    • 2013-03-31
    • 2015-06-02
    • 1970-01-01
    • 1970-01-01
    • 2019-07-12
    相关资源
    最近更新 更多