最大限度地减少 Python 脚本参数的代码重复(使用“argparse”或其他模块)

发布于 2025-01-11 14:37:12 字数 1263 浏览 1 评论 0原文

假设有多个脚本:script_1.pyscript_2.pyscript_3.pyscript_4.pyscript_5.pyscript_6.py 等,目标是最大限度地减少脚本作为输入的参数的代码重复。

作为场景示例:

  • script_1.pyscript_2.pyscript_3.py 有几个共同的参数 =>可能的解决方案:可以利用argparse的parent_parser
  • script_4.pyscript_5.pyscript_6.py有几个共同的参数=>可能的解决方案:可以利用argparse的parent_parser
  • script_5.py script_6.py script_7.py script_8.py有一个共同点 =>可能的解决方案:将 args 放入字典中(下面的片段示例)
"""
python run_app_w_argparse_example.py --arg_1 1
"""
import argparse
from typing import Dict

APPS_ARGS = {"--arg_1": dict(help="arg_1 description", type=int),
             "--arg_2": dict(help="arg_2 description", type=str, default="hi")}


def parser_example() -> Dict:
    parser = argparse.ArgumentParser(description="Description")
    parser.add_argument("--arg_1", **APPS_ARGS["--arg_1"])
    return vars(parser.parse_args())


if __name__ == '__main__':
    print(parser_example())

一个不方便的地方是“--arg1”在 add_argument 中重复两次。有办法避免这种情况吗?总体上有更好的解决方案吗?

Let's say one has several scripts: script_1.py, script_2.py, script_3.py, script_4.py, script_5.py, script_6.py, etc and the objective is to minimize code repetition in terms of arguments the scripts take as input.

As an example of scenarios:

  • script_1.py, script_2.py, script_3.py have several arguments in common => possible solution: one can leverage parent_parser of argparse
  • script_4.py, script_5.py, script_6.py have several arguments in common => possible solution: one can leverage parent_parser of argparse
  • script_5.py script_6.py script_7.py script_8.py have one argument in common => possible solution: put the args in a dictionary (snippet example below)
"""
python run_app_w_argparse_example.py --arg_1 1
"""
import argparse
from typing import Dict

APPS_ARGS = {"--arg_1": dict(help="arg_1 description", type=int),
             "--arg_2": dict(help="arg_2 description", type=str, default="hi")}


def parser_example() -> Dict:
    parser = argparse.ArgumentParser(description="Description")
    parser.add_argument("--arg_1", **APPS_ARGS["--arg_1"])
    return vars(parser.parse_args())


if __name__ == '__main__':
    print(parser_example())

One inconvenient is that "--arg1" gets repeated twice in add_argument. Is there a way to avoid that? Is there a better solution overall?

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

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

发布评论

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

评论(1

递刀给你 2025-01-18 14:37:12

这是我在使用子命令或有许多共享相同基本参数的脚本时偶尔用于 python 工具的模式。

简而言之,我创建了一个嵌套结构(我承认看起来有点可怕),它允许动态创建解析器。

基本布局是:

args = Tuple[Tuple[str, ..., dict], ...]

每个内部元组都包含 CLI 标志和参数选项的字典。
字典必须是最后一个元素。
这样做的原因是因为元组可以相互附加,因此参数可以堆叠起来。

import argparse

DEFAULT_SERVER_HOST = "127.0.0.1"
DEFAULT_SERVER_PORT = 5555
DEFAULT_TIMEOUT = 500

BASE_ARGS = (
    (
        "-H",  # FLAG
        "--host",  # FLAG
        dict(  # OPTIONS
            help="Server host address (default: {})".format(DEFAULT_SERVER_HOST),
            default=DEFAULT_SERVER_HOST,
        ),
    ),
    (
        "-P",
        "--port",
        dict(
            help="Server port (default: {})".format(DEFAULT_SERVER_PORT),
            default=DEFAULT_SERVER_PORT,
        ),
    ),
    (
        "-o",
        dict(type=str, help="Output filename", required=True),
    ),
    (
        "--timeout",
        dict(
            type=int,
            help="Connection timeout in seconds (default: {})".format(DEFAULT_TIMEOUT),
            default=DEFAULT_TIMEOUT,
        ),
    ),
)

def get_args(default_args=None, extra_args=None, prog=""):
    if default_args is None:
        args = BASE_ARGS
    else:
        args = default_args

    if extra_args is not None:
        args = args + extra_args

    parser = argparse.ArgumentParser(prog)

    for *flags, opts in args:
        parser.add_argument(*flags, **opts)

    return parser, parser.parse_args()

def main():
    extra_args = (
        (
            "--log-file",
            dict(help="File to write logs to"),
        ),
    )

    parser, args = get_args(extra_args=extra_args, prog="My script")
    print(args)

if __name__ == "__main__":
    main()

This is a pattern that I occasionally use for python tools when using sub-commands or there are many scripts that share the same base args.

In short I create a nested structure (that I admit looks a bit horrible) that allows the parser to be dynamically created.

The basic layout is:

args = Tuple[Tuple[str, ..., dict], ...]

Each inner tuple contains the CLI flags and a dict of the argument options.
the dict must be the final element.
The reason for doing it this way is because tuples can be appended to one another so arguments can be stacked up.

import argparse

DEFAULT_SERVER_HOST = "127.0.0.1"
DEFAULT_SERVER_PORT = 5555
DEFAULT_TIMEOUT = 500

BASE_ARGS = (
    (
        "-H",  # FLAG
        "--host",  # FLAG
        dict(  # OPTIONS
            help="Server host address (default: {})".format(DEFAULT_SERVER_HOST),
            default=DEFAULT_SERVER_HOST,
        ),
    ),
    (
        "-P",
        "--port",
        dict(
            help="Server port (default: {})".format(DEFAULT_SERVER_PORT),
            default=DEFAULT_SERVER_PORT,
        ),
    ),
    (
        "-o",
        dict(type=str, help="Output filename", required=True),
    ),
    (
        "--timeout",
        dict(
            type=int,
            help="Connection timeout in seconds (default: {})".format(DEFAULT_TIMEOUT),
            default=DEFAULT_TIMEOUT,
        ),
    ),
)

def get_args(default_args=None, extra_args=None, prog=""):
    if default_args is None:
        args = BASE_ARGS
    else:
        args = default_args

    if extra_args is not None:
        args = args + extra_args

    parser = argparse.ArgumentParser(prog)

    for *flags, opts in args:
        parser.add_argument(*flags, **opts)

    return parser, parser.parse_args()

def main():
    extra_args = (
        (
            "--log-file",
            dict(help="File to write logs to"),
        ),
    )

    parser, args = get_args(extra_args=extra_args, prog="My script")
    print(args)

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