Python点击和传递环境

问题描述 投票:0回答:1

我在将环境传递给子命令时遇到了一些问题。这是示例代码:

edis / main.py

import os
import importlib

import click

from edis.util import import_config


class Environment(object):

    def __init__(self):

        self.DEBUG = False


pass_environment = click.make_pass_decorator(Environment, ensure=True)
plugins_dir = os.path.abspath(
    os.path.join(
        os.path.dirname(__file__),
        "plugins"))

class PluginCommands(click.MultiCommand):

    def list_commands(self, ctx):
        rv = []
        for filename in os.listdir(plugins_dir):
            if filename.endswith(".py") and filename.startswith("cmd_"):
                rv.append(filename[4:-3])
        rv.sort()
        return rv

    def get_command(self, ctx, name):
        try:
            mod = importlib.import_module(f"edis.plugins.cmd_{name}")
        except ImportError:
            return
        return mod.cli


@click.command(cls=PluginCommands)
@click.option(
    '--debug',
    help='Enable debug mode',
    is_flag=True
)
@pass_environment
def cli(ctx, debug):
    print(f"1: {ctx.DEBUG}")
    if debug:
        ctx.DEBUG = True
    print(f"2: {ctx.DEBUG}")


if __name__ == '__main__':
    cli(obj={})

示例命令文件:

=== edis/plugins/cmd_test.py ===

import click

from edis.main import pass_environment

@click.group()
@pass_environment
def cli(ctx):
    print(f"3: {ctx.DEBUG}")


@cli.command('init')
@pass_environment
def init_cmd(ctx):
    print(f"4: {ctx.DEBUG}")


=== edis/plugins/cmd_init.py ===

import click
from edis.main import pass_environment

@click.command('init')
@pass_environment
def cli(ctx):
    print(f"3: {ctx.DEBUG}")

每当我现在运行我的简短程序时,都会看到未在子命令中设置DEBUG:

$ python -m edis.main
Usage: main.py [OPTIONS] COMMAND [ARGS]...

Options:
  --debug  Enable debug mode
  --help   Show this message and exit.

Commands:
  init
  test

$ python -m edis.main --debug test
1: False
2: True
Usage: main.py test [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  init

$ python -m edis.main --debug test init
1: False
2: True
3: False
4: False

$ python -m edis.main --debug init
1: False
2: True
3: False

我遵循了GIT储存库中的“ complex”示例,该示例按预期运行,因此我看不出任何真正的原因,为什么它在这里不起作用。我可以在数字1 + 2上看到回调已正确执行,但是ctx.DEBUG没有更新,因此没有传递给子命令。

有人对我有提示吗?谢谢。

问候,托马斯

python python-3.x click
1个回答
0
投票

我自己解决了这个问题。区别在于您如何运行脚本。我不是那个pythonista来解释为什么,但是我能做的就是发布答案。如果有人比我聪明,那么如果有人可以向我解释这一点,我会很高兴。

如果您像模块(python -m edis.main)一样启动脚本,则会发生这种情况:

python -m edis.main --debug test init
1: False
1a: False
2: True
2a: True
3: False
3a: False
4: False
4a: False

edis/main.py内部函数中所做的任何更改似乎都像在模块内部一样,就像局部变量一样,值得信任。但是,如果您在主Skript中调用模块,则它的工作方式将与预期的一样:

from edis.main import cli

if __name__ == '__main__':
    cli(obj={})

Output:
python run.py --debug test init
1: False
1a: False
2: True
2a: True
3: True
3a: True
4: True
4a: True

问候,托马斯

© www.soinside.com 2019 - 2024. All rights reserved.