Ich habe eine große Klickanwendung, die ich entwickelt habe, aber das Navigieren durch die verschiedenen Befehle/Unterbefehle wird immer schwieriger. Wie organisiere ich meine Befehle in separaten Dateien? Ist es möglich, Befehle und ihre Unterbefehle in separaten Klassen zu organisieren?
Hier ist ein Beispiel, wie ich es trennen möchte:
import click
@click.group()
@click.version_option()
def cli():
pass #Entry Point
@cli.group()
@click.pass_context
def cloudflare(ctx):
pass
@cloudflare.group('zone')
def cloudflare_zone():
pass
@cloudflare_zone.command('add')
@click.option('--jumpstart', '-j', default=True)
@click.option('--organization', '-o', default='')
@click.argument('url')
@click.pass_obj
@__cf_error_handler
def cloudflare_zone_add(ctx, url, jumpstart, organization):
pass
@cloudflare.group('record')
def cloudflare_record():
pass
@cloudflare_record.command('add')
@click.option('--ttl', '-t')
@click.argument('domain')
@click.argument('name')
@click.argument('type')
@click.argument('content')
@click.pass_obj
@__cf_error_handler
def cloudflare_record_add(ctx, domain, name, type, content, ttl):
pass
@cloudflare_record.command('edit')
@click.option('--ttl', '-t')
@click.argument('domain')
@click.argument('name')
@click.argument('type')
@click.argument('content')
@click.pass_obj
@__cf_error_handler
def cloudflare_record_edit(ctx, domain):
pass
@cli.group()
@click.pass_context
def uptimerobot(ctx):
pass
@uptimerobot.command('add')
@click.option('--alert', '-a', default=True)
@click.argument('name')
@click.argument('url')
@click.pass_obj
def uptimerobot_add(ctx, name, url, alert):
pass
@uptimerobot.command('delete')
@click.argument('names', nargs=-1, required=True)
@click.pass_obj
def uptimerobot_delete(ctx, names):
pass
Der Nachteil der Verwendung von CommandCollection
besteht darin, dass Ihre Befehle zusammengeführt werden und nur mit Befehlsgruppen funktioniert. Die bessere Alternative ist, add_command
zu verwenden, um das gleiche Ergebnis zu erzielen.
Ich habe ein Projekt mit dem folgenden Baum:
cli/
├── __init__.py
├── cli.py
├── group1
│ ├── __init__.py
│ ├── commands.py
└── group2
├── __init__.py
└── commands.py
Jeder Unterbefehl verfügt über ein eigenes Modul, wodurch die Verwaltung komplexer Implementierungen mit noch mehr Hilfsklassen und -dateien denkbar einfach ist. In jedem Modul enthält die commands.py
-Datei die @click
-Anmerkungen. Beispiel group2/commands.py
:
import click
@click.command()
def version():
"""Display the current version."""
click.echo(_read_version())
Bei Bedarf können Sie problemlos weitere Klassen im Modul und import
erstellen und hier verwenden, um Ihrer CLI die volle Leistungsfähigkeit der Klassen und Module von Python zu geben.
Mein cli.py
ist der Einstiegspunkt für die gesamte CLI:
import click
from .group1 import commands as group1
from .group2 import commands as group2
@click.group()
def entry_point():
pass
entry_point.add_command(group1.command_group)
entry_point.add_command(group2.version)
Mit diesem Setup ist es sehr einfach, Ihre Befehle nach Bedenken zu trennen und zusätzliche Funktionen um sie herum aufzubauen, die sie möglicherweise benötigen. Es hat mir bisher sehr gut gedient ...
Referenz: http://click.pocoo.org/6/quickstart/#nesting-commands
Angenommen, Ihr Projekt hat die folgende Struktur:
project/
├── __init__.py
├── init.py
└── commands
├── __init__.py
└── cloudflare.py
Gruppen sind nichts anderes als mehrere Befehle und Gruppen, die verschachtelt werden können. Sie können Ihre Gruppen in Module aufteilen und in Ihre init.py
-Datei importieren und sie mit dem add_command der cli
-Gruppe hinzufügen.
Hier ist ein init.py
Beispiel:
import click
from .commands.cloudflare import cloudflare
@click.group()
def cli():
pass
cli.add_command(cloudflare)
Sie müssen die Cloudflare-Gruppe importieren, die sich in der Datei cloudflare.py befindet. Ihr commands/cloudflare.py
würde so aussehen:
import click
@click.group()
def cloudflare():
pass
@cloudflare.command()
def zone():
click.echo('This is the zone subcommand of the cloudflare command')
Dann können Sie den Befehl cloudflare wie folgt ausführen:
$ python init.py cloudflare zone
Diese Informationen sind in der Dokumentation nicht sehr explizit. Wenn Sie jedoch den Quellcode betrachten, der sehr gut kommentiert ist, können Sie sehen, wie Gruppen verschachtelt werden können.
Ich suche im Moment nach so etwas wie diesem, in Ihrem Fall ist das einfach, weil Sie in jeder Datei Gruppen haben. Sie können dieses Problem lösen, wie in der Dokumentation beschrieben :
In der init.py
-Datei:
import click
from command_cloudflare import cloudflare
from command_uptimerobot import uptimerobot
cli = click.CommandCollection(sources=[cloudflare, uptimerobot])
if __== '__main__':
cli()
Das Beste an dieser Lösung ist, dass sie vollständig mit pep8 und anderen Linters kompatibel ist, da Sie nicht brauchen, etwas zu importieren, das Sie nicht verwenden würden, und Sie müssen * nicht von überall importieren.
Ich hoffe das hilft und sieht gut aus mit deinem cli.
Ich bin kein Click-Experte, aber es sollte funktionieren, indem Sie einfach Ihre Dateien in die Hauptdatei importieren. Ich würde alle Befehle in separaten Dateien verschieben und eine Hauptdatei haben, die die anderen importiert. Auf diese Weise ist es einfacher, die genaue Reihenfolge zu kontrollieren, falls dies für Sie wichtig ist. Ihre Hauptdatei würde also so aussehen:
import commands_main
import commands_cloudflare
import commands_uptimerobot