13

我正在尝试制作一个使用该argparse模块来解析命令行选项的 Python 程序。

我想创建一个可以命名或定位的可选参数。例如,我想做myScript --username=batmanmyScript batman. 我也希望myScript没有用户名有效。这可能吗?如果是这样,怎么办?

我尝试了类似于下面代码的各种事情,但没有成功。

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument("-u", "--user-name", default="admin")
group.add_argument("user-name", default="admin")
args = parser.parse_args()

编辑:上面的代码抛出一个异常说ValueError: mutually exclusive arguments must be optional.

我在 OS X 10.8.4 上使用 Python 2.7.2。

编辑:我尝试了 Gabriel Jacobsohn 的建议,但我无法让它在所有情况下都能正常工作。

我试过这个:

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument("-u", "--user-name", default="admin", nargs="?")
group.add_argument("user_name", default="admin", nargs="?")
args = parser.parse_args()
print(args)

和运行myScript batman会打印Namespace(user_name='batman'),但会打印。myScript -u batmanmyScript --user-name=batmanNamespace(user_name='admin')

我尝试将名称更改user-nameuser_name第一add_argument行,这有时会导致名称空间中的batmanadmin名称或错误,具体取决于我运行程序的方式。

我尝试将名称更改user_nameuser-name第二add_argument行,但这将打印Namespace(user-name='batman', user_name='admin')Namespace(user-name='admin', user_name='batman'),具体取决于我运行程序的方式。

4

3 回答 3

9

ArgumentParser的工作方式是在解析可选参数后始终检查任何尾随位置参数。因此,如果您有一个与可选参数同名的位置参数,并且它没有出现在命令行的任何位置,则可以保证覆盖可选参数(使用其默认值或None)。

坦率地说,这对我来说似乎是一个错误,至少在互斥组中使用时是这样,因为如果您明确指定了参数,那将是一个错误。

也就是说,我建议的解决方案是给位置参数一个不同的名称。

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument('-u','--username')
group.add_argument('static_username',nargs='?',default='admin')

然后在解析时,使用可选的用户名(如果存在),否则回退到位置static_username

results = parser.parse_args()
username = results.username or results.static_username

我意识到这不是一个特别巧妙的解决方案,但我认为任何答案都不会。

于 2013-07-23T12:30:48.737 回答
5

这是一个我认为可以满足您所有需求的解决方案:

import argparse
if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("-u", "--user-name", default="admin")
    # Gather all extra args into a list named "args.extra"
    parser.add_argument("extra", nargs='*')
    args = parser.parse_args()
    # Set args.user_name to first extra arg if it is not given and len(args.extra) > 0
    if args.user_name == parser.get_default("user_name") and args.extra:
        args.user_name = args.extra.pop(0)
    print args

如果您运行myScript -u batmanmyScript --user-name=batmanargs.user_name则设置为“蝙蝠侠”。如果这样做myScript batmanargs.user_name则再次设置为“蝙蝠侠”。最后,如果您只是这样做myScriptargs.user_name则设置为“管理员”。

此外,作为额外的奖励,您现在拥有所有传递给脚本的额外参数,这些参数存储在args.extra. 希望这可以帮助。

于 2013-07-23T02:37:49.033 回答
0

尝试使用 add_argument 方法的“nargs”参数。这种方式对我有用。现在您可以添加两次用户名,因此如果需要,您必须检查它并引发错误。

import argparse
if __name__ == '__main__':
   parser = argparse.ArgumentParser()
   parser.add_argument("-u", "--user-name", default="admin")
   parser.add_argument("user_name", default="admin", nargs="?")
   args = parser.parse_args()
   print(args)
于 2013-07-11T16:09:56.063 回答