我在将环境传递给子命令时遇到了一些问题。这是示例代码:
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没有更新,因此没有传递给子命令。
有人对我有提示吗?谢谢。
问候,托马斯
我自己解决了这个问题。区别在于您如何运行脚本。我不是那个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
问候,托马斯