如何解决Argparse 不会识别参数
此脚本将打印环境变量。
使用 Python 3.9。
目标是能够在需要时运行任何子命令。我得到的错误是,如果添加了任何额外的短标志,“忽略环境”arg 会尝试解析它。我不要这个。额外的短标志指向 --eval
之后分配的任何内容。
解析器.py
import argparse,os
def parseargs(p):
p.usage = '%(prog)s [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]'
p.add_argument(
"-i","--ignore-environment",action="store_const",const=dict(),dest="env",help="start with an empty environment",default=os.environ,)
p.add_argument(
"--export",nargs=1,help="Set argument with --export NAME=VALUE"
)
p.add_argument(
"--eval",nargs="+",help="Run any commands with newly updated environment,"
"--eval COMMAND ARGS"
)
return p
执行如下
>>> p = argparse.ArgumentParser()
>>> parseargs(p) # assigns arguments to parser
>>> p.parse_args('--export FOO=bar --eval cat test.py'.split()) # This is ok and works correctly. cat is the bash command
Namespace([os.environs..],eval=['cat','test.py'],export=['FOO=bar'])
>>>p.parse_args('--export FOO=bar --eval ls -l'.split()) # This is fails
error: unrecognized arguments: -l
如何让“-l”被“-i/ignore environment”忽略但传递给eval,例如使用cat test.py
。我曾尝试使用 sub_parser 但无济于事。出现同样的结果。
解决方法
问题在于,parse_args
在考虑任何实际选项的语义之前,会尝试从词法上识别可能选项。
由于采用可变数量参数的选项几乎必须是始终使用的 last 选项,请考虑将 --eval
设置为一个标志,用于告诉您的程序如何解释剩余的位置参数。那么ls
和-l
可以被--
抵消,防止parse_args
认为-l
是一个未定义的选项。
p.add_argument(
"--eval",action='store_true',help="Run any commands with newly updated environment,"
)
# zero or more,so that you don't have to provide a dummy argument
# when the lack of --eval makes a command unnecessary.
# Wart: you can still use --eval without specifying any commands.
# I don't believe argparse alone is capable of handling this,# at least not in a way that is simpler than just validating
# arguments after calling parse_args().
p.add_argument('cmd_and_args',nargs='*')
那么你的命令行可能看起来像
>>> p.parse_args('--export FOO=bar --eval -- ls -l'.split())
甚至
>>> p.parse_args('--eval --export FOO=bar -- ls -l'.split())
稍后,您将使用 args.eval
的布尔值来决定如何处理列表 args.cmd_and_args
。
重要提示: 一个问题是,您将这些选项附加到任意预先存在的解析器,这些解析器可能定义了自己的位置参数,因此让它与原始解析器配合使用可能会很好很难,如果不是不可能的话。
另一种选择是采用单个参数进行内部解析。
p.add_arguments("--eval")
...
args = p.parse_args()
cmd_and_args = shlex.split(args.eval) # or similar
然后
>>> p.parse_args(['--export','FOO=bar','--eval','ls -l'])
(请注意,使用 str.split
不适用于 --export FOO=bar --eval "ls -l"
之类的命令行。)
如果您的位置参数必须以 - 开头并且看起来不像负数,则可以插入伪参数“--”,它告诉 parse_args() 之后的所有内容都是位置参数 [... ]
因此,在您的情况下,您无法更改添加或定义参数的方式,但是您提供的要解析的字符串应该在 eval 选项的参数前面有 --
,如下所示:
--export FOO=bar --eval ls -- -l
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。