Python argparse 的动态参数
我在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"都会出现"unrecognized arguments"的错误。
我尝试了我能想到的所有方法,但到目前为止都没有成功。有没有Python高手能给我一些建议?
2 个回答
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
14
正如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')