python - 使用 argparse 解析“安装样式”选项
问题描述
在 python 中解析“安装样式”选项的最佳选择是什么?
我需要解析argument=value
与特定参数关联的列表,如下例所示:
myprogram --database type=mysql,user=root,passwd=secret,database=mydb --mail type=imap,server=imap.my.domain,user=myself,passwd=othersecret,port=999 --whatever key=val,key=val2,etcetera
我的第一个猜测是指定一个参数,然后手动解析它(仅示例代码):
from argparse import ArgumentParser
parser = ArgumentParser(description='Example only')
parser.add_argument('-D', '--database', nargs=1)
parser.add_argument('-M', '--mail', nargs=1)
parser.add_argument('-W', '--whatever', nargs=1)
args = parser.parse_args('--database type=mysql,user=root,passwd=secret,database=mydb --mail type=imap,server=imap.my.domain,user=myself,passwd=othersecret,port=999 --whatever key=val,key=val2,etcetera'.split())
def parse(a):
d = {}
for x in a.split(','):
try:
k, v = x.split('=')
except ValueError:
k = x
v = None
d[k] = v
args.database = parse(args.database)
args.mail = parse(args.mail)
args.whatever = parse(args.whatever)
...但我想知道是否有更好的方法。
解决方案
事实证明,处理这个问题的正确方法是实现一个自定义argparse.Action
.
在特定情况下,这是合理的工作:
!/bin/env python3
from argparse import ArgumentParser, Action
class KeypairAction(Action):
def __init__(self, option_strings, dest, keys=None, **kwargs):
super().__init__(option_strings, dest, **kwargs)
if keys is None:
raise ValueError('must define "keys" argument')
if isinstance(keys, dict):
self.keys = keys
elif isinstance(keys, (list, tuple)):
self.keys = {}
for k in keys:
if isinstance(k, tuple):
k, v = k
else:
v = None
self.keys[k] = v
def __call__(self, parser, namespace, values, option_string=None):
d = {}
for x in values.split(','):
try:
k, v = x.split('=')
except ValueError:
k = x
v = None
d[k] = v
setattr(namespace, self.dest, d)
ap = ArgumentParser(description="My nice program")
ap.add_argument('-D', '--database', action=KeypairAction, keys=('type', 'host', 'port', 'user', 'pass', 'db'))
ap.add_argument('-M', '--mail', action=KeypairAction, keys=('type', 'host', 'port', 'user', 'pass'))
ap.add_argument('-W', '--whatever', action=KeypairAction, keys=('key1', 'key2', 'key3', 'etcetera'))
args = ap.parse_args('--database type=mysql,user=root,pass=secret,db=mydb '
'--mail type=imap,host=imap.my.domain,user=myself,pass=othersecret,port=999 '
'--whatever key1=val,key2=val2,etcetera'.split())
print(args)
这可以简单地扩展以处理默认值。
推荐阅读
- python - 试图将列表框放在页面中间,滚动条在右边
- c - 发出阅读线并在c中一起打印所有内容
- android-recyclerview - 如何在 RecyclerView 的 CardView 中实现对 Item Click 的操作以显示结果
- r - 为 R 中的位置频率矩阵绘制具有离散 x 轴的序列徽标
- python - 尽管在 Python 中握手失败,但仍获取服务器证书
- json - 我想在 tableview javafx 中显示我的 json 数据
- javascript - Javascript - 在 for 循环中附加数据
- c - Visual Studio 未返回正确的 C 浮点值
- python - 检查序数日期时间是否在当前日期时间之后?
- python - 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以获得在 \'keyword")\' 附近使用的正确语法