使用 argparse 处理子进程的参数:"Expected one argument"
Processing arguments for subprocesses using argparse: "Expected one argument"
首先,我很抱歉标题没有完全说明我的问题是什么,我有点挣扎,所以我将用一个可重现的例子更清楚地说明它:
我有以下代码:
example.py:
import argparse
def parse_args():
"""Command line argument parser
Returns:
The extra arguments
"""
parser = argparse.ArgumentParser(description="Arguments for test runner")
parser.add_argument('-e', '--extra_args', type=str, default="", help="Extra arguments. Enter as a single line encapsulated by quotes. Example: -e \"--repeat=0 otherstuff -x anotherpositional\"")
arguments = parser.parse_args()
return arguments
if __name__ == "__main__":
args = parse_args()
print(args.extra_args)
然后 --extra_args
参数将用作子进程调用的位置参数。
我需要传递的参数如下:--repeat=0
。它不起作用,我得到以下结果:
python example.py -e "toto" # This print toto
python example.py -e "--repeat = 0" # This print --repeat = 0
python example.py -e "--repeat" # error: argument -e/--extra_args: expected one argument
python example.py -e "--repeat=0" # error: argument -e/--extra_args: expected one argument
我的理解是解析器将 --repeat
作为参数处理,找不到它的值,然后中断。但不幸的是,我别无选择,只能写“--repeat=0”,因为软件接收它。
您知道解决方法吗?
我找到了一个丑陋的解决方法,但如果它退出,我会喜欢更好的解决方案。
我添加了以下功能:
def __workaround_for_extra_utr_args():
"""This workaround is necessary because utr can receives args at \"--repeat=0\" which are not processable by arg parse, even as a string"""
import sys
index_of_extra_args = [sys.argv.index(v) for v in ['-e', '--extra_utr_args'] if v in sys.argv]
space = " "
if index_of_extra_args:
index_of_extra_args = index_of_extra_args[0]
if space not in sys.argv[index_of_extra_args + 1]:
sys.argv[index_of_extra_args + 1] = sys.argv[index_of_extra_args + 1] + space
在调用解析器之前调用它,就可以return这个字符串,然后可以在解析后去掉多余的space。
parse_args
解释 arg 字符串开头的双破折号的方式似乎有问题。
如果您添加前缀,它可以是单个字符,例如字符串中的 space,这可能是一种解决方法。
python example.py -e " --repeat=0" # OK
python example.py -e ":--repeat=0" # OK
python example.py -e " --repeat=0 --foo=1 --boo=2" # OK
然后在您的代码中去除第一个字符或任何前缀的 extra_args 会很容易。
import argparse
def parse_args():
"""Command line argument parser
Returns:
A tuple containing the toolset version and a force flag
"""
parser = argparse.ArgumentParser(description="Arguments for test runner")
parser.add_argument('-e', '--extra_args', type=str, default="", help="Extra arguments. Enter as a single line encapsulated by quotes. Example: -e \"--repeat=0 otherstuff -x anotherpositional\"")
arguments = parser.parse_args()
arguments.extra_args = arguments.extra_args[1:]
return arguments
if __name__ == "__main__":
args = parse_args()
print(args.extra_args)
不理想,但一个简单的解决方法。
处理以“--”开头的值是 argparse
的一个挑战。它标记一个标志(与您的 --extra_args
一样)的想法是 argparse
不可或缺的一部分,因此很难解决它。
简单地添加引号没有帮助。它们控制 shell 处理字符串的方式,但不会改变 sys.argv
.
中的内容
https://docs.python.org/3/library/argparse.html#arguments-containing
描述了 pseudo-argument“--”的用法,但这只适用于位置参数。 (我不得不再次查看代码以了解为什么它对可选值没有任何作用。)
因此:
parser = argparse.ArgumentParser(description="Arguments for test runner")
parser.add_argument('extra_args', nargs='*')
arguments = parser.parse_known_args()
print(arguments)
我得到:
919:~/mypy$ python3 stack72129874.py -- --repeat
argv ['stack72129874.py', '--', '--repeat']
(Namespace(extra_args=['--repeat']), [])
0919:~/mypy$ python3 stack72129874.py -- --repeat=0
argv ['stack72129874.py', '--', '--repeat=0']
(Namespace(extra_args=['--repeat=0']), [])
0920:~/mypy$ python3 stack72129874.py -- --repeat = 0
argv ['stack72129874.py', '--', '--repeat', '=', '0']
(Namespace(extra_args=['--repeat', '=', '0']), [])
0920:~/mypy$ python3 stack72129874.py -- "--repeat = 0"
argv ['stack72129874.py', '--', '--repeat = 0']
(Namespace(extra_args=['--repeat = 0']), [])
有一个 nargs=argparse.REMAINDER
与 pseudo-argument 类似,但同样只适用于位置。而且在使用上有一些问题,所以现在没有记录。
添加空格,例如“--repeat = 0”,在之前关于该主题的 SO 中已经提到。
如果您真的不需要 argparse
机制的其余部分(帮助、错误处理、其他参数),那么您自己解析 sys.argv
是一个完美的解决方案。
首先,我很抱歉标题没有完全说明我的问题是什么,我有点挣扎,所以我将用一个可重现的例子更清楚地说明它:
我有以下代码:
example.py:
import argparse
def parse_args():
"""Command line argument parser
Returns:
The extra arguments
"""
parser = argparse.ArgumentParser(description="Arguments for test runner")
parser.add_argument('-e', '--extra_args', type=str, default="", help="Extra arguments. Enter as a single line encapsulated by quotes. Example: -e \"--repeat=0 otherstuff -x anotherpositional\"")
arguments = parser.parse_args()
return arguments
if __name__ == "__main__":
args = parse_args()
print(args.extra_args)
然后 --extra_args
参数将用作子进程调用的位置参数。
我需要传递的参数如下:--repeat=0
。它不起作用,我得到以下结果:
python example.py -e "toto" # This print toto
python example.py -e "--repeat = 0" # This print --repeat = 0
python example.py -e "--repeat" # error: argument -e/--extra_args: expected one argument
python example.py -e "--repeat=0" # error: argument -e/--extra_args: expected one argument
我的理解是解析器将 --repeat
作为参数处理,找不到它的值,然后中断。但不幸的是,我别无选择,只能写“--repeat=0”,因为软件接收它。
您知道解决方法吗?
我找到了一个丑陋的解决方法,但如果它退出,我会喜欢更好的解决方案。
我添加了以下功能:
def __workaround_for_extra_utr_args():
"""This workaround is necessary because utr can receives args at \"--repeat=0\" which are not processable by arg parse, even as a string"""
import sys
index_of_extra_args = [sys.argv.index(v) for v in ['-e', '--extra_utr_args'] if v in sys.argv]
space = " "
if index_of_extra_args:
index_of_extra_args = index_of_extra_args[0]
if space not in sys.argv[index_of_extra_args + 1]:
sys.argv[index_of_extra_args + 1] = sys.argv[index_of_extra_args + 1] + space
在调用解析器之前调用它,就可以return这个字符串,然后可以在解析后去掉多余的space。
parse_args
解释 arg 字符串开头的双破折号的方式似乎有问题。
如果您添加前缀,它可以是单个字符,例如字符串中的 space,这可能是一种解决方法。
python example.py -e " --repeat=0" # OK
python example.py -e ":--repeat=0" # OK
python example.py -e " --repeat=0 --foo=1 --boo=2" # OK
然后在您的代码中去除第一个字符或任何前缀的 extra_args 会很容易。
import argparse
def parse_args():
"""Command line argument parser
Returns:
A tuple containing the toolset version and a force flag
"""
parser = argparse.ArgumentParser(description="Arguments for test runner")
parser.add_argument('-e', '--extra_args', type=str, default="", help="Extra arguments. Enter as a single line encapsulated by quotes. Example: -e \"--repeat=0 otherstuff -x anotherpositional\"")
arguments = parser.parse_args()
arguments.extra_args = arguments.extra_args[1:]
return arguments
if __name__ == "__main__":
args = parse_args()
print(args.extra_args)
不理想,但一个简单的解决方法。
处理以“--”开头的值是 argparse
的一个挑战。它标记一个标志(与您的 --extra_args
一样)的想法是 argparse
不可或缺的一部分,因此很难解决它。
简单地添加引号没有帮助。它们控制 shell 处理字符串的方式,但不会改变 sys.argv
.
https://docs.python.org/3/library/argparse.html#arguments-containing
描述了 pseudo-argument“--”的用法,但这只适用于位置参数。 (我不得不再次查看代码以了解为什么它对可选值没有任何作用。)
因此:
parser = argparse.ArgumentParser(description="Arguments for test runner")
parser.add_argument('extra_args', nargs='*')
arguments = parser.parse_known_args()
print(arguments)
我得到:
919:~/mypy$ python3 stack72129874.py -- --repeat
argv ['stack72129874.py', '--', '--repeat']
(Namespace(extra_args=['--repeat']), [])
0919:~/mypy$ python3 stack72129874.py -- --repeat=0
argv ['stack72129874.py', '--', '--repeat=0']
(Namespace(extra_args=['--repeat=0']), [])
0920:~/mypy$ python3 stack72129874.py -- --repeat = 0
argv ['stack72129874.py', '--', '--repeat', '=', '0']
(Namespace(extra_args=['--repeat', '=', '0']), [])
0920:~/mypy$ python3 stack72129874.py -- "--repeat = 0"
argv ['stack72129874.py', '--', '--repeat = 0']
(Namespace(extra_args=['--repeat = 0']), [])
有一个 nargs=argparse.REMAINDER
与 pseudo-argument 类似,但同样只适用于位置。而且在使用上有一些问题,所以现在没有记录。
添加空格,例如“--repeat = 0”,在之前关于该主题的 SO 中已经提到。
如果您真的不需要 argparse
机制的其余部分(帮助、错误处理、其他参数),那么您自己解析 sys.argv
是一个完美的解决方案。