我有一个带有 3-4 个参数的解析器,效果很好。我想向脚本提供未知数量的额外参数,这些参数将被加载到模板中。我已阅读 argparse 文档,但我不确定这是否可能。我可以
parse_known_arguments()
,但我仍然必须自己处理["--placeholder1", "value1", "--placeholder2", "value2", ...]
数组。我应该继续这样做,还是有更Pythonic的方式?
从我的头顶开始:
parser = argparse.ArgumentParser()
parser.add_argument("--template", required=True)
parser.add_argument("--location", required=True)
args,unknown = parser.parse_known_arguments()
tpl = LoadTemplate(args.template)
# Missing part where I transform unknown into an dict or namespace called extraarguments
raw = tpl.render(extraarguments)
# Print into args.location raw
render.py --template template1 --location /path/to/invoices --author John --customer Customer1 --title "Your invoice is ready!"
render.py --template template2 --location /path/to/newsletter --customer Customer2 --sender [email protected] --subject "Weekly newsletter"
在这两种情况下,
template
和location
都必须存在,但额外的参数应该被解包并发送到模板渲染函数中。它看起来像一句简单的话,但是有没有一种更Pythonic的方法来做到这一点?
假设
unknown
列表是键和值的交替列表,则可以将其转换为字典:
adict = dict(zip(unknown[:-1:2],unknown[1::2]))
zip 部分将列表转换为对列表,然后将其转换为字典。您可能需要对这些值进行更多处理,以从键中删除“--”前缀。如果您需要检查错误,例如不匹配的“键值”序列,您可能需要更明确的迭代。
这是一个完整保留“--”的版本:
templates = {'template1': "from: {--author} to: {--customer} re: {--title}",
'template2': "from: {--sender} to: {--customer} re: {--subject}"}
def parser():
parser = argparse.ArgumentParser()
parser.add_argument("--template", required=True, choices=templates)
parser.add_argument("--location", required=True)
args,unknown = parser.parse_known_args()
extraarguments = dict(zip(unknown[::2], unknown[1::2]))
tpl = templates[args.template]
raw = tpl.format(**extraarguments)
return raw
print parser()
使用您的 2 个样品,将产生:
In [25]: run stack30139426.py --template template1 --location /path/to/invoices --author John --customer Customer1 --title "Your invoice is ready!"
from: John to: Customer1 re: Your invoice is ready!
In [26]: run stack30139426.py --template template2 --location /path/to/newsletter --customer Customer2 --sender [email protected] --subject "Weekly newsletter"
from: [email protected] to: Customer2 re: Weekly newsletter
还有其他关于输入字典或其他未知键/值对的问题。
一个建议是使用
key:value
语法,然后使用简单的 [kv.split(':') for kv in unknowns]
来生成对列表:
run stack30139426.py --template template2 --location /path/to/newsletter customer:Customer2 sender:[email protected] subject:"Weekly newsletter"
另一种是使用 JSON 语法
run stack30139426.py --template template2 --location /path/to/newsletter '{"customer":"Customer2", "sender":"[email protected]", "subject":"Weekly newsletter"}'
部分自动化该过程的一种方法可以是通过使用
argparse
中以 '--' 开头的字符串作为参数名称创建另一个解析器来重用 unknown
:
argument_names = [arg for arg in unknown if arg[:2] == '--']
parser = argparse.ArgumentParser()
for arg in argument_names:
parser.add_argument(arg)
args = parser.parse_args(unknown)
但是,如果提供了名称-值对之外的任何内容,这将会失败。