Python argparse:可以命名或定位的命令行参数
Posted
技术标签:
【中文标题】Python argparse:可以命名或定位的命令行参数【英文标题】:Python argparse: command-line argument that can be either named or positional 【发布时间】:2013-07-10 00:08:47 【问题描述】:我正在尝试制作一个使用 argparse
模块解析命令行选项的 Python 程序。
我想创建一个可以命名或定位的可选参数。例如,我希望myScript --username=batman
与myScript 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 batman
和myScript --user-name=batman
将打印Namespace(user_name='admin')
。
我尝试在第一行add_argument
中将名称user-name
更改为user_name
,这有时会导致命名空间中的batman
和admin
出现错误,具体取决于我运行程序的方式。
我尝试在第二行add_argument
中将名称user_name
更改为user-name
,但这会打印Namespace(user-name='batman', user_name='admin')
或Namespace(user-name='admin', user_name='batman')
,具体取决于我运行程序的方式。
【问题讨论】:
我想提一下,我正在尝试做的事情与Ack 对其--match
参数所做的事情基本相同。
请看这个question
不知何故我没有注意到这个问题。随意将此问题标记为该问题的副本。
【参考方案1】:
尝试使用 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)
【讨论】:
我尝试了您答案中的代码。当我运行myScript batman
但使用myScript -u batman
或myScript --user-name=batman
时,它运行良好,它忽略了我的参数并将user_name
值设置为admin
。【参考方案2】:
这是一个我认为可以满足您所有需求的解决方案:
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 batman
或myScript --user-name=batman
,args.user_name
将设置为“蝙蝠侠”。如果您执行myScript batman
,args.user_name
将再次设置为“蝙蝠侠”。最后,如果你只做myScript
,args.user_name
会被设置为 'admin'。
另外,作为一个额外的好处,您现在将所有传递给脚本的额外参数存储在args.extra
中。希望这会有所帮助。
【讨论】:
我会将args.username = args.extra[0]
更改为args.username=args.extra.pop(0)
,这样它就不会出现在两个地方。
@Perkins:嗯……我喜欢这样。它使脚本更干净。让我做吧
我喜欢你的回答。我做了一个小改动以避免在两个地方使用默认用户名。
我决定将赏金奖励给@James Holderness。我喜欢你的想法,但詹姆斯的解决方案向用户表明,对程序的调用不允许同时具有命名用户名和位置用户名。【参考方案3】:
ArgumentParser 的工作方式是,它总是在解析可选参数后检查任何尾随位置参数。因此,如果您有一个与可选参数同名的位置参数,并且它没有出现在命令行的任何位置,则可以保证覆盖可选参数(使用其默认值或 None )。
坦率地说,这对我来说似乎是一个错误,至少在互斥组中使用时是这样,因为如果您明确指定了参数,那将是一个错误。
也就是说,我建议的解决方案是给位置参数一个不同的名称。
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument('-u','--username')
group.add_argument('static_username',nargs='?',default='admin')
然后在解析时,如果存在,则使用可选的 username,否则回退到位置 static_username。
results = parser.parse_args()
username = results.username or results.static_username
我意识到这不是一个特别巧妙的解决方案,但我认为任何答案都不会。
【讨论】:
以上是关于Python argparse:可以命名或定位的命令行参数的主要内容,如果未能解决你的问题,请参考以下文章