简体   繁体   English

我可以指示 Python 的 argparse 将位置 arg 之后的所有 arguments 视为也是位置的,即使它们与可选 arg 匹配?

[英]Can I direct Python's argparse to treat all arguments after a positional arg as also positional, even if they match an optional arg?

I am writing a utility (call it runner ) which, as its main functionality, runs another script.我正在编写一个实用程序(称为runner ),它的主要功能是运行另一个脚本。 That script to be run is passed as an argument, as well as any arguments that should be passed to the script.要运行的脚本以及应传递给脚本的任何 arguments 作为参数传递。 So, for example:因此,例如:

runner script.py arg1 arg2

will run script.py as a subprocess, with arg1 and arg2 as arguments.script.py作为子进程运行, arg1arg2为 arguments。 This is easy enough, using the following:这很容易,使用以下内容:

parser = argparse.ArgumentParser()

parser.add_argument("script", help="The script to run")
parser.add_argument("script_args", nargs="*", help="Script arguments", default=[])

args = parser.parse_args()

The complication is that I have some additional arguments passed to runner , which modify how the script will be called.复杂之处在于我有一些额外的 arguments 传递给runner ,它修改了脚本的调用方式。 One of these is --times , which will be used to determine how many times to run the script.其中之一是--times ,它将用于确定运行脚本的次数。 So:所以:

runner --times 3 script.py arg1 arg2

will run script.py three times, with arg1 and arg2 as arguments.将运行script.py三次, arg1arg2为 arguments。

The problem I am trying to solve is this.我要解决的问题是这个。 I want any arguments after the script name to be treated as arguments to pass to the script, even if they match argument names of runner .我希望脚本名称之后的任何 arguments 都被视为 arguments 传递给脚本,即使它们与runner的参数名称匹配 So:所以:

runner script.py arg1 arg2 --times 3

should run script.py once , and pass the arguments arg1 , arg2 , --times , and 3 to script.py.应该运行 script.py一次,并将--times arg1arg2 、--times 和3传递给 script.py。

I can't find any way to tell the ArgumentParser to treat all arguments after the script arg as positional.我找不到任何方法告诉 ArgumentParser 将script arg 之后的所有 arguments 视为位置。

I know the caller of the script could force this behavior using the -- special argument , so the following would yield the desired behavior:我知道脚本的调用者可以使用-- 特殊参数强制执行此行为,因此以下将产生所需的行为:

runner -- script.py arg1 arg2 --times 3

but I want the program to take care of this instead.但我希望程序来处理这个问题。 Is this behavior possible?这种行为可能吗?

First of all, you should not do this.首先,你不应该这样做。 It is more clear, if you make it explicit which arguments apply to which program (call), maybe you can sourround the whole script parameters of the called script in quotations like:更清楚的是,如果您明确指出哪个 arguments 适用于哪个程序(调用),也许您可以将被调用脚本的整个脚本参数用引号括起来,例如:

runner script.py "arg1 arg2 --times 3"

But if you want to do this your way, you can overwrite the ArgumentParser.parse_arguments function with your own.但是,如果您想以自己的方式执行此操作,则可以用自己的方式覆盖ArgumentParser.parse_arguments function。 I only build an example to illustrate how it is possible (for me it's working), but i do not know if there are any sideeffects:我只是建立一个例子来说明它是如何可能的(对我来说它正在工作),但我不知道是否有任何副作用:

import argparse
from typing import Optional, Sequence


class ErrorCatchingArgumentParser(argparse.ArgumentParser):

    def parse_args(self, args: Optional[Sequence[str]] = ...) -> argparse.Namespace:
        ns, a = super().parse_known_args(args=args)
        args.insert(args.index(ns.script), "--")

        return super().parse_args(args=args)


if __name__ == '__main__':
    arguments = ["--time", "3", "myscript", "my_args", "myargs2", "--time", "5"]

    parser = ErrorCatchingArgumentParser()

    parser.add_argument("script", help="The script to run")
    parser.add_argument("--time", help="The script to run")
    parser.add_argument("script_args", nargs="*", help="Script arguments", default=[])

    print(arguments)
    namespace = parser.parse_args(arguments)

    print(arguments)
    print(namespace)

Output: Output:

['--time', '3', 'myscript', 'my_args', 'myargs2', '--time', '5']
['--time', '3', '--', 'myscript', 'my_args', 'myargs2', '--time', '5']
Namespace(script='myscript', time='3', script_args=['my_args', 'myargs2', '--time', '5'])

It

  1. parses the given args with parse_known_args of superclass to get all arguments set (and do not raise an error)使用超类的parse_known_args解析给定的 args 以获取所有 arguments 集(并且不引发错误)
  2. search for your script variable and insert the -- before it in the argument list搜索您的script变量并在参数列表中插入--之前
  3. parses the arguments with the parse_args function of superclass to get "the real" arguments使用超类的parse_args function 解析 arguments 以获得“真正的” arguments

In the output you can see the original arguments, the manipulated arguments and the created namespace.在 output 中,您可以看到原始的 arguments、操纵的 arguments 和创建的命名空间。

But i think you should NOT do this, anyway.但我认为你不应该这样做,无论如何。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM