Mar*_*ark 5 python command-line-arguments argparse
假设我有一个 yaml 输入文件 (input.txt),其中包含以下内容:
names: [Bob, Jill]
ages: [22, 31]
county: somewhere
Run Code Online (Sandbox Code Playgroud)
我的代码来解析这个:
import yaml
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--name', default=[], dest='names', action='append')
parser.add_argument('--age', default=[], dest='ages', action='append')
parser.add_argument('--county', dest='county')
parser.add_argument(
'--config-file',
dest='config_file',
type=argparse.FileType(mode='r'))
args = parser.parse_args()
print args
Run Code Online (Sandbox Code Playgroud)
我的问题是这样的:我见过许多网站显示如何为配置文件添加参数,如上面所示。如何“解析”该配置文件并将其中的值添加(附加)到命令行上传递的任何值?
如果我的程序名为 so.py,并且像这样调用:
so.py --config-file=input.txt --name 'Ralph' --age 40
Run Code Online (Sandbox Code Playgroud)
我想在我的参数中获得名称= ['鲍勃','吉尔','拉尔夫']年龄= [22,31,40]县='某处'。这可能吗?
有一个参数允许从文件输入,“fromfile-prefix-chars”
https://docs.python.org/3/library/argparse.html#fromfile-prefix-chars
在默认形式中,每行需要一个命令行字符串。但文档还展示了如何修改它以从每行获取多个字符串。您可以采用这个想法并将其扩展以处理 Yaml 语法。
但有些库可以读取配置和 yaml 文件。因此,您可以使用您的--config-file参数来读取带有该库的文件,然后将其结果与结果合并argparse。通过将两者(yaml 和 argparse)转换为字典并使用该.update方法,合并可能是最简单的。
Ipython使用其配置文件(默认文件和用户指定的文件)来填充其argparse解析器参数。因此,用户配置文件可以覆盖默认设置,并且命令行可以覆盖两者。执行此操作的代码不适合胆小的人,但对于大型项目可能值得研究。
有关如何进行合并的详细信息取决于“yaml”生成的对象。是argparse args一个简单的类型对象argparse.Namespace。有关详细信息,请参阅文档。通常人们只是从 中“读取”值args,但添加或修改值同样容易。如果你愿意的话,vars(args)可以把它变成一本字典。
使用yaml.load(并稍微简化 argparse):
import yaml
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--names', action='append')
parser.add_argument('--ages', action='append')
parser.add_argument('--county', dest='county')
parser.add_argument('--config-file') # automatic - to _ conversion
sample = "--config-file=stack28220581.yaml --name Ralph --age 40".split()
args = parser.parse_args(sample)
# add test that len(args.names)==len(args.ages) ??
with open(args.config_file) as f:
ydict = yaml.load(f)
# {'county': 'somewhere', 'names': ['Bob', 'Jill'], 'ages': [22, 31]}
# add list attributes from args to the corresponding ydict values
for k,v in ydict.items():
av = getattr(args,k,None)
if av and isinstance(v, list):
v.extend(av)
print(ydict)
# {'names': ['Bob', 'Jill', 'Ralph'], 'ages': [22, 31, '40'], 'county': 'somewhere'}
Run Code Online (Sandbox Code Playgroud)
使用示例prefix_chars:
def foo(astr):
# custom convert_arg_line_to_args method
# convert 'names: [v1,v2]' into ['--names', v1, '--names', v2, ...]
alist = []
if ':' not in astr:
return astr
field,value = astr.split(':')
value = value.strip()
field = '--'+field
if value.startswith('['):
values = value[1:-1].split(',')
for v in values:
alist.extend([field,v.strip()])
else:
alist.extend([field, value])
return alist
parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
parser.convert_arg_line_to_args = foo # could also do this with subclass
parser.add_argument('--names', action='append')
parser.add_argument('--ages', action='append')
parser.add_argument('--county', dest='county')
sample = "@stack28220581.yaml --name Ralph --age 40".split()
args = parser.parse_args(sample)
print(args)
# Namespace(ages=['22', '31', '40'], county='somewhere', names=['Bob', 'Jill', 'Ralph'])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2464 次 |
| 最近记录: |