Python Argparse将无法识别参数
此脚本将打印环境变量。Python Argparse将无法识别参数,python,argparse,Python,Argparse,此脚本将打印环境变量。 使用Python3.9。 目标是能够在需要时运行任何子命令。我得到的错误是,如果添加了任何其他短标志,“ignore-environment”参数将尝试对其进行解析。我不要这个。附加的短标志用于在--eval之后分配的任何内容 parser.py import argparse, os def parseargs(p): p.usage = '%(prog)s [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]
使用Python3.9。 目标是能够在需要时运行任何子命令。我得到的错误是,如果添加了任何其他短标志,“ignore-environment”参数将尝试对其进行解析。我不要这个。附加的短标志用于在
--eval
之后分配的任何内容
parser.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_解析器,但没有用。同样的结果也会出现。问题在于,parse_args
在考虑任何实际选项的语义之前,尝试从词汇上识别可能的选项
因为一个选择变量的数目几乎必须是最后使用的选项,请考虑使用<代码> -EVA/CODE>一个标志,它用来告诉程序如何解释剩余的正负参数。然后,
ls
和-l
可以被--
抵消,防止解析参数
思考-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_和_args
重要提示:其中的一个缺点是,您将这些选项附加到任意的预先存在的解析器上,这些解析器可能定义了它们自己的位置参数,因此,如果不是不可能的话,让这些选项与原始解析器配合使用可能会很困难
另一个选项是采用单个参数进行内部解析
p.add_arguments("--eval")
...
args = p.parse_args()
cmd_and_args = shlex.split(args.eval) # or similar
然后
(请注意,使用str.split
对于像--export FOO=bar--eval“ls-l”
这样的命令行是行不通的):
如果位置参数必须以-并且看起来不像负数,则可以插入伪参数“--”,它告诉parse_args()后面的所有内容都是位置参数[…]
因此,在您的情况下,您无法更改添加或定义参数的方式,但是您提供的要解析的字符串应该在eval选项的参数前面有--
,如下所示:
--export FOO=bar --eval ls -- -l
--eval ls \-l
?@9769953 shell在执行脚本之前执行引号删除argparse
仍将看到--eval
、ls
、和-l
@chepner这里没有shell。但实际上,argparse在尝试时会将其解析为一个literal```。对,因为反斜杠转义是一个特定于shell的特性argparse
没有任何这样的概念。但是,-l
是一个位置参数,而不是--eval
选项的参数。您必须对解析器进行重大调整。我不知道--
。非常感谢。
--export FOO=bar --eval ls -- -l