我正在使用argparse的动作将各种数据添加到类中。如果命令行没有提供arg,我想在默认值上使用该操作。这可能吗? 谢谢!
答案 0 :(得分:5)
argparse
时, action
不会使用default
。它只使用setattr
。如果默认值是字符串,它可以使用type
。但您可以直接调用action
。
这里我使用了从文档中借用的自定义操作类。在第一个parse_args
没有任何反应。然后我创建一个新的namespace
,并在默认情况下调用该操作。然后我将该命名空间传递给parse_args
。要理解这一点,您需要将其导入交互式shell,并检查命名空间和操作的属性。
# sample custom action from docs
class FooAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
print('Setting: %r %r %r' % (namespace, values, option_string))
setattr(namespace, self.dest, 'action:'+values)
p = argparse.ArgumentParser()
a1 = p.add_argument('--foo', action=FooAction, default='default')
print 'action:',a1
print p.parse_args([])
ns = argparse.Namespace()
a1(p, ns, a1.default, 'no string') # call action
print p.parse_args([],ns)
print p.parse_args(['--foo','1'],ns)
产生:
action: FooAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default='default', type=None, choices=None, help=None, metavar=None)
Namespace(foo='default')
Setting: Namespace() 'default' 'no string'
Namespace(foo='action:default')
Setting: Namespace(foo='action:default') '1' '--foo'
Namespace(foo='action:1')
我定制了输出以突出显示何时使用该动作。
这是一种对参数执行特殊操作的方法,该参数未在命令行中给出(或者使用值==给出默认值)。这是https://stackoverflow.com/a/24638908/901925中给出的类的简化。
class Parser1:
def __init__(self, desc):
self.parser = argparse.ArgumentParser(description=desc)
self.actions = []
def milestone(self, help_='milestone for latest release.', default=None):
action = self.parser.add_argument('-m', '--milestone', help=help_, default=default)
self.actions.append(action)
return self
def parse(self):
args = self.parser.parse_args()
for a in self.actions:
if getattr(args, a.dest) == a.default:
print 'Please specify', a.dest
values = raw_input('>')
setattr(args, a.dest, values)
return args
print Parser1('desc').milestone(default='PROMPT').parse()
提示在parse_args
之后完成。我认为没有理由再次致电parse_args
。
答案 1 :(得分:0)
如果没有指定选项,我需要提示用户 - 这就是我的做法:
class _PromptUserAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
if values == self.default:
print 'Please specify', self.dest
values = raw_input('>')
setattr(namespace, self.dest, values)
class Parser:
def __init__(self, desc, add_h=True):
self.parser = argparse.ArgumentParser(description=desc, add_help=add_h,
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
#actions to be run on options if not specified (using default to check)
self.actions = []
@staticmethod
def new(description, add_help=True):
return Parser(description, add_help)
# ...
def milestone(self, help_='Specify the milestone for latest release.'):
action = self.parser.add_argument('-m', '--milestone',
dest='milestone',
action=_PromptUserAction,
default='PROMPT', # needed I think
type=str,
help=help_)
self.actions.append(action)
return self
def parse(self):
"""
Return an object which can be used to get the arguments as in:
parser_instance.parse().milestone
:return: ArgumentParser
"""
args = self.parser.parse_args()
# see: http://stackoverflow.com/a/21588198/281545
dic = vars(args)
ns = argparse.Namespace()
for a in self.actions:
if dic[a.dest] == a.default:
a(self.parser, ns, a.default) # call action
# duh - can I avoid it ?
import sys
return self.parser.parse_args(sys.argv[1:],ns)
我感兴趣的是,如果能够以某种方式完成,而不必重新解析args(import sys
部分)。也许是argparse.Action
的一些构造函数选项?