Argparse 不会识别参数
Argparse will not recognize arguments
此脚本将打印环境变量。
使用 Python 3.9。
如果需要,目标是能够 运行 任何子命令。我得到的错误是,如果添加任何额外的短标志,“忽略环境”arg 正在尝试解析它。我不想要这个。在 --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 环境”忽略但传递给 eval,就像使用 cat test.py
一样。我试过使用 sub_parser 但无济于事。出现相同的结果。
问题是 parse_args
在考虑任何实际选项的语义之前尝试从词法上识别 可能的 选项。
由于参数数量可变的选项几乎必须是 last 选项,因此请考虑使 --eval
成为一个标志,用于告诉您的编写如何解释其余 positonal 参数的程序。那么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"
这样的命令行。)
If you have positional arguments that must begin with - and don’t look like negative numbers, you can insert the pseudo-argument '--' which tells parse_args() that everything after that is a positional argument [...]
因此,在您的情况下,您无法对添加或定义参数的方式进行任何更改,但是您提供的要解析的字符串应该在 eval 选项的参数之前有 --
,因为这样:
--export FOO=bar --eval ls -- -l
此脚本将打印环境变量。
使用 Python 3.9。
如果需要,目标是能够 运行 任何子命令。我得到的错误是,如果添加任何额外的短标志,“忽略环境”arg 正在尝试解析它。我不想要这个。在 --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 环境”忽略但传递给 eval,就像使用 cat test.py
一样。我试过使用 sub_parser 但无济于事。出现相同的结果。
问题是 parse_args
在考虑任何实际选项的语义之前尝试从词法上识别 可能的 选项。
由于参数数量可变的选项几乎必须是 last 选项,因此请考虑使 --eval
成为一个标志,用于告诉您的编写如何解释其余 positonal 参数的程序。那么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"
这样的命令行。)
If you have positional arguments that must begin with - and don’t look like negative numbers, you can insert the pseudo-argument '--' which tells parse_args() that everything after that is a positional argument [...]
因此,在您的情况下,您无法对添加或定义参数的方式进行任何更改,但是您提供的要解析的字符串应该在 eval 选项的参数之前有 --
,因为这样:
--export FOO=bar --eval ls -- -l