如何使用argparse返回选项字符串?

时间:2015-06-07 04:02:08

标签: python popen argparse

parser = argparse.ArgumentParser()
parser.add_argument("-p", "--pattern", help="Pattern file")
args = parser.parse_args()

现在可以从"--pattern"取回字符串args吗? 我需要字符串,以便我可以构建一个cmd列表以传递给Popen,如Popen(['some_other_program', args.pattern.option_string, args.pattern], ...)而不重复它(并且必须在两个地方维护它)(Popen(['some_other_prog', '--pattern', args.pattern], ...))。

我需要为另一个程序创建一个包装器。有些args需要传递给包装程序(通过Popen),有些是包装器所必需的。

有比下面的例子更好的方法吗?

pass_1 = '--to-be-passed'
parser = argparse.ArgumentParser()
parser.add_argument("-p", pass_1, help="Pass me on")
parser.add_argument("-k", "--arg-for-wrapper")
args = parser.parse_args()

...
process = Popen(['wrapped_program', pass_1, args.pass_1], ...)
... 

这种将args保存在变量中的方法并不是很好:

  1. 维持短期期权和长期期权变得困难。
  2. Popen如果在另一个函数中调用,则需要将这些变量(或它们的dict)传递给函数。这似乎是多余的,因为传递给它的args就足够了。

3 个答案:

答案 0 :(得分:2)

dest来电中添加add_argument

parser.add_argmument("p", "--pattern", dest="pattern", help="your help text")
args = parser.parse_args()
args = vars(args)

您可以使用args["pattern"]引用该模式。

答案 1 :(得分:2)

似乎没有一种简单的方法可以从parser.parse_args()的结果中获取原始选项字符串,但是您可以从parser对象中获取它们。您只需要查看其__dict__,以便在创建后检索parser设置。在您的情况下,您需要_option_string_actions字段。不幸的是,这似乎没有得到官方的支持,因为我找不到专用于此的ArgumentParser方法,所以YMMV。在Python 3上:

演示:

parser = argparse.ArgumentParser()
parser.add_argument('--foo', '-f', type=int, default=1000, help='intensity of bar')
parser.add_argument('--bar', '-b', type=str, default='bla', help='whatever')
store_action_dict=vars(parser)['_option_string_actions']
print(store_action_dict.keys())    # dict_keys(['--help', '-b', '-f', '-h', '--foo', '--bar'])

答案 2 :(得分:1)

删除的答案和评论表明您对所需内容存在一些疑惑。所以我会增加这种困惑。

通常,解析器不会记录选项字符串。但是,它会提供给Action __call__方法。因此自定义Action类可以保存它。 argparse文档中的FooAction自定义类示例说明了这一点。

如果我定义了这个动作的子类:

In [324]: class PassThru(argparse._StoreAction):
def __call__(self, parser, namespace, values, option_string=None):
    setattr(namespace, self.dest, [values, option_string])

In [324]: p.add_argument('-o','--other',action=PassThru)

选项字符串与值一起记录(' -o'或' - 其他'):

In [322]: p.parse_args('-p test -o teseting'.split())
Out[322]: Namespace(other=['teseting', '-o'], pass_me_on='test')

In [323]: p.parse_args('-p test --other teseting'.split())
Out[323]: Namespace(other=['teseting', '--other'], pass_me_on='test')

显然,option_string和value可以以不同的顺序记录在字典中,作为命名空间中的单独属性等。

还有其他方法可以将选项传递给另一个程序,特别是如果包装解析器本身不需要处理它们。

argparsesys.argv[1:]获取参数,但不会更改它。因此,即使您的解析器使用了某些参数,您也可以将该列表传递给popen(全部或部分)。

argparse docs在nargs=REMAINDER下有一个例子,它为自己解析一些参数,然后收集剩下的参数传递给另一个程序。这是他们的例子:

>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo')
>>> parser.add_argument('command')
>>> parser.add_argument('args', nargs=argparse.REMAINDER)
>>> print(parser.parse_args('--foo B cmd --arg1 XX ZZ'.split()))
Namespace(args=['--arg1', 'XX', 'ZZ'], command='cmd', foo='B')

所以你可以用{/ p>之类的东西来呼叫popen

plist = ['wrapped_program']
plist.extend(args.args)
popen(plist, ...)

使用parse.parse_known_args也可用于将未解析的单词收集到“附加内容”中。名单。这部分文档讨论了将这些字符串传递给另一个程序(就像你正在做的那样)。与REMAINDER案例相比,额外的东西不一定是最后的。

当然,只有当这个解析器本身不需要--pattern时,这些工作才有效。如果它解析它,它就不会出现在REMAINDER或extras中。在这种情况下,您必须将其添加回您提供的列表popen

我会调整你的解析器:

pass_1 = 'passed'  # without the -- or internal -
dpass_` = '--'+pass_
parser = argparse.ArgumentParser()
parser.add_argument("-p", dpass_1, help="Pass me on")
parser.add_argument("-k", "--arg-for-wrapper")
args = parser.parse_args()
process = Popen(['wrapped_program', dpass_1, getattr(args, pass_1)], ...)

另一种选择:

parser = argparse.ArgumentParser()
pass_action = parser.add_argument("-p", '--pass-me-on', help="Pass me on")
parser.add_argument("-k", "--arg-for-wrapper")
args = parser.parse_args()

如果您打印pass_action(在shell中),您将获得以下内容:

 _StoreAction(option_strings=['-p', '--pass-me-on'], dest='pass_me_on', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)

因此,您可以从该对象中提取--namedest,因此:

process = Popen(['wrapped_program', pass_action.option_strings[-1], getattr(args, pass_action.dest), ...], ...)

您必须查看sys.argv以查看使用了哪个option_string(长,短或其他)。解析器不会记录任何地方。

注意' - 传递给我'制作dest='pass_me_on'。将-转换为_会使从另一个字符串中获取一个字符串变得复杂。

如果您有dest字符串,则必须使用getattr从args命名空间中提取它,或使用vars(args)[dest](字典访问)。

另一个问题。如果--pattennargs='+', its value will be a list, as opposed to a string. You'd have to careful when merging that into the popen`参数列表。