使用Argparse处理子过程的论点:“期望一个参数”

发布于 2025-01-26 08:36:29 字数 1168 浏览 1 评论 0原文

首先,我对标题对我的问题没有一个完美的想法感到抱歉,我对此有点挣扎,所以我将以可复制的例子更清楚地说明它:

我有以下代码:

< strong>示例

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)

我需要传递的参数是以下一个:- 重复= 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 = 0'。

您知道周围有任何解决方法吗?

First of all, I am sorry about the title that does not give a perfect idea of what my problem is, I kinda struggled with it, so I am going to illustrate it more clearly with a reproducible example:

I have the following code:

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)

The --extra_args argument is then going to be used as a positional argument for a subprocess call.

The argument I need to pass is the following one: --repeat=0. It does not work, I got the following results:

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

What I understand is that the parser process the --repeat as an argument, find no value for it, and breaks. But unfortunately I have no choice than to write '--repeat=0' all attached, because of the software receiving it.

Would you know any workaround around it ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

隔岸观火 2025-02-02 08:36:29

似乎parse_args intepret在ARG字符串开始时的双重破折号似乎存在问题。

如果添加前缀,它可能是单个字符,例如字符串中的空间,这可能是解决方法。

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)

不是理想的,但是很容易。

It seems there is a problem with the way parse_args inteprets the double dash at the beginning of the arg string.

If you add a prefix, it could be a single character, like a space within the string, this could be a workaround.

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

It would be easy then in your code to strip the extra_args of the first character or whatever prefix.

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)

Not ideal but an easy workaround.

半岛未凉 2025-02-02 08:36:29

argparse为挑战的处理值是' - '开头的值。它标记一个标志的想法(如- extra_args)与argparse是如此不可或缺,因此很难围绕它使用。

简单地添加报价无济于事。他们控制外壳如何处理字符串,但否则不会更改sys.argv中的内容。

https://docs.pypython.org/3/library/argparse。 html#包含参数的

描述了伪王的使用“ - ”,但这仅适用于位置参数。 (我必须再次查看代码,以了解为什么它对选项不做任何事情。)

所以:

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一样 - 辩论,但仅针对位置。并且使用它存在一些问题,因此现在没有证件。

上一个关于该主题的添加诸如“ - repeat = 0”之类的空间。

而且,如果您真的不需要argparse机械(帮助,错误处理,其他参数)解决方案。

Handling values that start with a '--' is a challenge with argparse. The idea that it marks a flag (as with your --extra_args) is so integral to argparse, that it's hard to work around it.

Simply adding quotes doesn't help. They control how the shell handles the strings, but doesn't otherwise change what's in sys.argv.

https://docs.python.org/3/library/argparse.html#arguments-containing

describes the use of pseudo-argument "--", but that only works for positional arguments. (I'd have to look at the code again to see why it doesn't do anything with optionals.)

So with:

parser = argparse.ArgumentParser(description="Arguments for test runner")
parser.add_argument('extra_args', nargs='*')
arguments = parser.parse_known_args()
print(arguments)

I get:

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']), [])

There is a nargs=argparse.REMAINDER that works like the pseudo-argument, but again only for positionals. And there are some problem with using it, so it's now undocumented.

Adding spaces such as in " --repeat = 0" has been mentioned in previous SO about the topic.

And if you don't really need the rest of the argparse machinery (help, error handling, other arguments), doing your own parsing of sys.argv is a perfectly find solution.

把昨日还给我 2025-02-02 08:36:29

我找到了一个丑陋的解决方法,但是如果它退出,我会享受更好的解决方案。

我添加了以下功能:

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

在调用解析器之前调用它,并且它将能够返回字符串,然后可以在解析后删除额外的空间。

I found an ugly workaround but if it exit, I would enjoy a better solution.

I added the following function:

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

Call it before calling the parser, and it will be able to return the string, it is then possible to remove the extra space after the parsing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文