【问题标题】:How to split my subcommands in several files in Python 3.6 and Click 7.1.2如何在 Python 3.6 中将我的子命令拆分为多个文件并单击 7.1.2
【发布时间】:2021-01-13 18:29:46
【问题描述】:

为了更清晰,我想在不同的文件中实现每个子命令。
现在我只有一个,但我的想法是随着时间的推移添加更多。

为此,我尝试了 2 种方法,但都以失败告终...

基本上我尝试得到这个结果:

$ test_cli
Usage: test_cli [OPTIONS] COMMAND [ARGS]...

  Cli command

Options:
  --help  Show this message and exit.

Commands:
  test  Test command.


$ test_cli test hello
Hello !

这是文件

$ tree
.
├── cli.py
├── setup.py
└── test.py

我正在使用 virtualenv,我使用以下命令来测试我的应用程序:

$ pip install --editable .

setup.py 的代码是相同的:

from setuptools import setup

setup(
    name = 'test_cli',
    version = '1.0',
    py_modules = [ 'cli', 'test' ],
    install_requires = [
        'Click',
    ],
    entry_points = '''
        [console_scripts]
        test_cli=cli:cli
    ''',
)

尝试 1 - 失败

基于此link 的代码,但它不适用于我...

这是每个文件的代码:

cli.py

import click
import test

@click.group()
def cli():
    ''' Cli command '''
    pass

cli.add_command(test)

test.py

import click


@click.group()
def test():
    ''' Test command. '''
    pass


@test.command()
def hello():
    click.echo('Hello !')

这是我遇到的错误:

Traceback (most recent call last):
  File "/tmp/myenv/bin/test_cli", line 33, in <module>
    sys.exit(load_entry_point('test-cli', 'console_scripts', 'test_cli')())
  File "/tmp/myenv/bin/test_cli", line 25, in importlib_load_entry_point
    return next(matches).load()
  File "/tmp/myenv/lib/python3.6/site-packages/importlib_metadata/__init__.py", line 105, in load
    module = import_module(match.group('module'))
  File "/usr/lib64/python3.6/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 994, in _gcd_import
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/tmp/toto/cli.py", line 9, in <module>
    cli.add_command(test)
  File "/tmp/myenv/lib/python3.6/site-packages/click/core.py", line 1347, in add_command
    name = name or cmd.name
    AttributeError: module 'test' has no attribute 'name'

尝试 2 - 失败

这次我找到了一个代码here。我没有任何错误,但我无法执行任何子命令:-/

cli.py

import click
import test

@click.group()
def cli():
    ''' Cli command '''
    pass

导入点击 导入剪辑

test.py

import click
import cli

@cli.group()
def test():
    ''' Test command. '''
    pass

@test.command()
def hello():
    click.echo('Hello !')

当我执行尝试执行子命令时,我遇到了这个问题:

$ test_cli test hello
Usage: test_cli [OPTIONS] COMMAND [ARGS]...
Try 'test_cli --help' for help.

Error: No such command 'test'.

知道这个问题吗?
谢谢。

【问题讨论】:

  • 在您的第一次尝试中,您正在添加调用add_command(test),但testtest 模块,而不是test **命令-将是test.testtest 模块的test 属性,即命令。换句话说,尝试使用cli.add_command(test.test) :)

标签: python-3.x python-click


【解决方案1】:

最简单的方法是为您的 CLI 实现一个单独的 .py 文件并将函数导入其中。我已经在自己的程序中实现了这一点:

控制台.py

import click
from .main import store, retrieve

@click.group()
def cli():
    pass

@cli.command(no_args_is_help=True)
(series of @click.arguments)
def store(application, key, expiration, userdata):
    # sends the arguments directly to the "store" function in main.py
    store(application,key,expiration,userdata)

(other commands)
if __name__ == '__main__':
    cli()

在 main.py 中

def store(app, key, expiration, userdata):
    """Program for a user to submit a user-generated API key to their database."""
    # The actual function doing its work, in a separate file

此方法将您的 CLI 设置与实际代码分开,同时允许完全访问所有点击功能,包括组、子命令等。它还允许您从许多不同的模块调用命令,甚至在 CLI 中调用外部命令(例如,如果您想要一个 CLI 来整合来自不同包的多个功能,请先搁置关于这是否是适当行为的讨论)。

【讨论】:

    【解决方案2】:

    在您的第一个示例中,您需要将测试组导入到您的模块中。

    cli.py

    import click
    from test import test 
    
    
    @click.group()
    def cli():
        ''' Cli command '''
        pass
    
    
    cli.add_command(test)
    
    if __name__ == '__main__':
        cli()
    

    test.py

    import click
    
    
    @click.group()
    def test():
        ''' Test command. '''
        pass
    
    
    @test.command()
    def hello():
        click.echo('Hello !')
    

    【讨论】:

      猜你喜欢
      • 2016-04-11
      • 1970-01-01
      • 2021-11-18
      • 1970-01-01
      • 2020-06-11
      • 2017-04-08
      • 2016-10-04
      • 1970-01-01
      • 2021-07-29
      相关资源
      最近更新 更多