YSC*_*YSC 4 python python-2.7 argparse
我想parser.add_argument(...)在我的代码中使用常量定义构建一个to map参数.
假设我有以下内容
import argparse
# Both are the same type
CONST_A = <something>
CONST_B = <otherthing>
parser = argparse.ArgumentParser()
parser.add_argument(...)
# I'd like the following to be true:
parser.parse_args("--foo A".split()).foo == CONST_A
parser.parse_args("--foo B".split()).foo == CONST_B
Run Code Online (Sandbox Code Playgroud)
我能代替...什么呢?
我能做的最好的const是:
import argparse
# Both are the same type
CONST_A = 10
CONST_B = 20
parser = argparse.ArgumentParser()
status_group = parser.add_mutually_exclusive_group(required=True)
status_group.add_argument("-a", const=CONST_A, action='store_const')
status_group.add_argument("-b", const=CONST_B, action='store_const')
# I'd like the following to be true:
print parser.parse_args("-a".split()).a == CONST_A # True
print parser.parse_args("-b".split()).b == CONST_B # True
Run Code Online (Sandbox Code Playgroud)
需要注意的是常量保存到TW odifferent属性a和b,女巫适合我不:(
最简单的方法是取的优势,type=在选择add_argument像@hpaulj做虽然可以用一个工厂函数来概括:
def argconv(**convs):
def parse_argument(arg):
if arg in convs:
return convs[arg]
else:
msg = "invalid choice: {!r} (choose from {})"
choices = ", ".join(sorted(repr(choice) for choice in convs.keys()))
raise argparse.ArgumentTypeError(msg.format(arg,choices))
return parse_argument
Run Code Online (Sandbox Code Playgroud)
然后代替...使用type=argconv(A=CONST_A, B=CONST_B):
parser.add_argument("--foo", type=argconv(A=CONST_A, B=CONST_B))
Run Code Online (Sandbox Code Playgroud)
然后一切都会按照你想要的那样在你的例子中运行.
以下是我发布的第一个答案,它仍然有效但并不像上面的解决方案那么简单.
另一种方法是创建一个继承自argparse.ArgumentParser和重写的类,parse_args以便在生成结果时修改结果:
import argparse
class MappedParser(argparse.ArgumentParser):
mapping = {} #backup if you don't use def_mapping
def def_mapping(self,**options):
self.mapping = options
def parse_args(self,args=None,namespace=None):
result = argparse.ArgumentParser.parse_args(self,args,namespace)
for name,options in self.mapping.items(): #by default this is is empty so the loop is skipped
if name in result:
key = getattr(result,name)
if key in options:
replace_with = options[key]
setattr(result,name,replace_with)
else:
self.error("option {name!r} got invalid value: {key!r}\n must be one of {valid}".format(name=name,key=key,valid=tuple(options.keys())))
return #error should exit program but I'll leave this just to be safe.
return result
Run Code Online (Sandbox Code Playgroud)
这样你的(示例)程序的其余部分将如下所示:
# There is nothing restricting their type.
CONST_A = "<something>"
CONST_B = ["other value", "type is irrelevent"]
parser = MappedParser() #constructor is same
parser.def_mapping(foo={"A":CONST_A, "B":CONST_B})
parser.add_argument("--foo") # and this is unchanged
# the following is now true:
print(parser.parse_args("--foo A".split()).foo is CONST_A)
print(parser.parse_args("--foo B".split()).foo is CONST_B)
#note that 'is' operator works so it is even the same reference
#this gives decent error message
parser.parse_args("--foo INVALID".split())
print("when parser.error() is called the program ends so this never is printed")
Run Code Online (Sandbox Code Playgroud)
添加这样的额外选项:
parser.def_mapping(foo={"A":CONST_A, "B":CONST_B,"C":"third option"})
Run Code Online (Sandbox Code Playgroud)
或者像这样的额外参数:
parser.def_mapping(foo={"A":CONST_A, "B":CONST_B},
conv={"int":int,"float":float})
Run Code Online (Sandbox Code Playgroud)
以及未指定的任何添加的参数都是def_mapping独立的,因此很容易实现.
| 归档时间: |
|
| 查看次数: |
848 次 |
| 最近记录: |