- Gooey verwandelt Python-3-Konsolenanwendungen in benutzerfreundliche GUI-Anwendungen und funktioniert, indem einer Funktion mit einer
argparse-Deklaration eine einzelne Decorator-Zeile hinzugefügt wird
- Die Standardinstallation ist mit
pip install Gooey möglich. Verwendet man den @Gooey-Decorator zusammen mit ArgumentParser, liest Gooey die Argumente und erstellt eine UI auf Basis von WX-Komponenten
- Wenn die Standard-Widget-Auswahl nicht ausreicht, kann man
GooeyParser als Ersatz für ArgumentParser einsetzen und über das Argument widget benutzerdefinierte Widgets wie FileChooser, DateChooser, PasswordField oder Slider auswählen
- Die Zielgruppe sind nicht primär Werkzeuge für Entwickler, die direkt mit der CLI arbeiten, sondern eher Büro-Skripte nach dem Muster „ausführen und fertig“ oder Tools für Nicht-Programmierer. Unterstützt werden Ausführungsmodi für erweitert/einfach/ohne Konfiguration sowie Menüs, Fortschrittsanzeige, Internationalisierung, Icon-Anpassung und Packaging
- Dynamische Validierung und Lifecycle-Events sind als experimentelle Funktionen gekennzeichnet.
optparse wird derzeit nicht unterstützt; vorausgesetzt wird Code auf Basis von ArgumentParser sowie optionales Event-Subscription
Wie Konsolenprogramme in GUIs verwandelt werden
- Gooey wandelt Konsolenanwendungen in GUI-Anwendungen um, die für Endnutzer leicht bedienbar sind
- Die zentrale Nutzung besteht darin, einen
@Gooey-Decorator an eine Funktion mit argparse-Deklaration anzuhängen
from gooey import Gooey
@Gooey
def main():
parser = ArgumentParser(...)
# rest of code
- Stil und Verhalten lassen sich über Decorator-Argumente anpassen
advanced: ob der Bildschirm für erweiterte Einstellungen angezeigt wird
language: Auswahl einer JSON-basierten Übersetzung
auto_start: Einstellungsbildschirm überspringen und sofort starten
target: Befehl festlegen, der als Subprozess ausgeführt wird
program_name, program_description: Anzeigename und Beschreibung in der GUI
default_size: anfängliche Größe der GUI
dump_build_config, load_build_config: Gooey-Build-Konfiguration als JSON speichern/laden
monospace_display: Festbreitenschrift in der Ausgabemaske verwenden
Installation und Beispiele
- Der einfachste Installationsweg ist pip
pip install Gooey
- Alternativ kann man das Repository klonen und durch Ausführen von
setup.py installieren
git clone https://github.com/chriskiehl/Gooey.git
python setup.py install
- Vorgefertigte Beispielskripte gibt es im Repository Gooey Examples
- Das Beispiel-Repository dient dazu, verschiedene Layouts, Widgets und Funktionen von Gooey auszuprobieren
Warum das nützlich ist
- Gooey wurde entwickelt, um das Problem zu verringern, Nutzern eine Kommandozeile zu zeigen, mit der sie nicht vertraut sind
- Wenn ein Programm eine oder mehrere Aufgaben ausführen soll, muss es Optionen entgegennehmen. Bisher musste man entweder selbst eine GUI bauen oder erklären, wie Argumente an eine Konsolenanwendung übergeben werden
- Gooey ermöglicht es Entwicklern, Programme weiterhin auf vertraute Weise zu konfigurieren und zugleich Anzeige und Interaktion über eine GUI bereitzustellen
Geeignete Zielgruppe und ungeeignete Fälle
- Für Utilities für einen selbst oder andere Programmierer sowie für Tools, deren Ausgabe in andere Konsolenanwendungen gepiped werden soll, ist Gooey möglicherweise nicht geeignet
- Für Büro-Ausführungsskripte, Werkzeuge zum Verschieben von Daten von Ort A nach B und Programme für Nicht-Programmierer ist es gut geeignet
- Das Ziel ist, komplexe Anwendungen zu bauen und die GUI ohne Zusatzkosten gleich mitzubekommen
Interne Funktionsweise und argparse-Mapping
- Gooey parst zur Laufzeit Referenzen auf
ArgumentParser in Python-Skripten
optparse wird derzeit nicht unterstützt
- Extrahierten Argumenten wird abhängig von der bereitgestellten
action ein Komponententyp zugewiesen, der für den GUI-Aufbau verwendet wird
ArgumentParser._actions wird standardmäßig auf folgende WX-Komponenten abgebildet
store: TextCtrl
store_const, store_true, store_False, version: CheckBox
append: TextCtrl
count: DropDown
Mutually Exclusive Group: RadioGroup
choice: DropDown
GooeyParser und benutzerdefinierte Widgets
- Wenn die Standard-Widget-Auswahl nicht ausreicht, kann GooeyParser als Drop-in-Ersatz für
ArgumentParser verwendet werden
GooeyParser bietet das zusätzliche Keyword-Argument widget, mit dem der Name der anzuzeigenden Komponente festgelegt wird
from gooey import Gooey, GooeyParser
@Gooey
def main():
parser = GooeyParser(description="My Cool GUI Program!")
parser.add_argument('Filename', widget="FileChooser")
parser.add_argument('Date', widget="DateChooser")
- Zu den unterstützten benutzerdefinierten Widgets gehören
DirChooser, FileChooser, MultiFileChooser
FileSaver, MultiFileSaver
DateChooser, TimeChooser
PasswordField
Listbox
BlockCheckbox
ColourChooser
FilterableDropdown
IntegerField, DecimalField
Slider
- Werte, die
DateChooser und TimeChooser an die Anwendung übergeben, sind immer im ISO format; in Teilen der GUI können lokal angepasste Werte entsprechend den Einstellungen des Endnutzers angezeigt werden
BlockCheckbox verschiebt bei langen Hilfetexten den Textblock an eine normale Position und zeigt neben dem Steuerelement ein kurzes block_label an, damit die Darstellung besser aussieht als bei einer normalen Inline-Checkbox
Internationalisierung
- Gooey wählt die Anzeigesprache über das Decorator-Argument
language
@Gooey(language='russian')
def main():
...
- Sämtliche Programmtexte werden in externen JSON-Dateien gespeichert
- Unterstützung für eine neue Sprache wird hinzugefügt, indem Schlüssel/Wert-Paare im Verzeichnis
gooey/languages/ ergänzt werden
- Derzeit werden standardmäßig mehr als 18 Übersetzungen mitgeliefert
Globale Einstellungen und UI-Konfiguration
- Das allgemeine Erscheinungsbild und Verhalten von Gooey wird über Decorator-Argumente angepasst
- Zu den wichtigsten Einstellungen gehören
encoding: Zeichencodierung für die Anzeige, Standard ist utf-8
advanced: Auswahl zwischen vollständigem Einstellungsbildschirm und vereinfachter Ansicht
auto_start: sofort ausführen, ohne Einstellungen
target: festlegen, wie Gooey sich selbst erneut ausführt
suppress_gooey_flag: verhindert beim Einsatz eines benutzerdefinierten target das Einfügen zusätzlicher CLI-Parameter
fullscreen: im Vollbildmodus starten
image_dir: Verzeichnis für benutzerdefinierte Bilder/Icons
language_dir: Verzeichnis für benutzerdefinierte Sprachdateien
disable_stop_button, show_stop_warning: Steuerung von Stopp-Button und Warnung während der Ausführung
show_success_modal, show_failure_modal: ob Zusammenfassungsmodale für Erfolg/Fehler angezeigt werden
run_validators: ob vor dem Programmaufruf Validierung ausgeführt wird
progress_regex, progress_expr: Parsen und Umwandeln von Fortschrittstext
navigation: TABBED oder SIDEBAR
body_bg_color, header_bg_color, footer_bg_color, sidebar_bg_color: Farbeinstellungen
terminal_font_family, terminal_font_size, terminal_font_color: Schriftarteinstellungen für die Terminalanzeige
menus: benutzerdefinierte Menügruppen und Einträge
clear_before_run: vorherige Ausgabe vor erneutem Ausführen löschen
Layout und Ausführungsmodi
- Gooey teilt Eingaben standardmäßig in zwei Gruppen auf:
positional und optional
- Mit
add_argument_group() von argparse können Eingaben logisch gruppiert und das Layout der Gruppen angepasst werden
parser = ArgumentParser()
search_group = parser.add_argument_group(
"Search Options",
"Customize the search options"
)
search_group.add_argument(
'--query',
help='Base search string'
)
Menüfunktionen
- Seit Gooey 1.0.2 kann oben eine Menüleiste hinzugefügt werden
- Menüs werden als Liste von Maps in der Form
@Gooey(menu=[{}, {}, ...]) angegeben
- Jede Menügruppe hat
name und items
- Jeder Menüeintrag enthält immer
type und menuTitle
- Unterstützte Typen für Menüeinträge sind
AboutDialog: zeigt Programminformationen wie Name, Version und Lizenz an
MessageDialog: zeigt dem Nutzer eine informative Nachricht an
Link: öffnet die angegebene URL im Standardbrowser
HtmlDialog: zeigt einen Dialog mit einer eingeschränkten HTML-Teilmenge an
Dynamische Validierung
- Dynamic Validation ist eine experimentelle Funktion, deren API sich ändern oder entfernt werden kann
- Gooey kann Benutzereingaben optional vorab validieren, bevor sie an das Programm übergeben werden
- Diese Funktion nutzt den
type-Parameter, der bei den meisten Argparse-Argumenttypen verwendet werden kann
def must_be_exactly_ten(value):
number = int(value)
if number == 10:
return number
else:
raise TypeError("Hey! you need to provide exactly the number 10!")
- Validierung wird standardmäßig nicht ausgeführt
- Um sie zu aktivieren, muss das Event
VALIDATE_FORM abonniert werden
from gooey import Gooey, Events
@Gooey(use_events=[Events.VALIDATE_FORM])
def main():
...
- Diese Funktion ist derzeit Opt-in, weil intern starkes Monkey Patching eingesetzt wird
Lifecycle-Events und UI-Steuerung
- Seit Gooey 1.2.0 stellt Gooey dem Programm Lifecycle-Hooks bereit
- Auch diese Funktion ist experimentell und ihre API kann sich ändern oder entfernt werden
- Derzeit gibt es zwei zentrale Hooks
- Beide Hooks werden nach Abschluss des Prozesses ausgeführt
- Handler erhalten das geparste Argparse-Objekt und den aktuellen Zustand der Gooey-UI; wenn sie einen aktualisierten Zustand zurückgeben, kann dieser in der UI übernommen werden
- Handler werden beim Erzeugen von
GooeyParser verknüpft
parser = GooeyParser(
on_success=my_success_handler,
on_failure=my_failure_handler)
- Für die Nutzung müssen die Events explizit abonniert werden
from gooey import Gooey, Events
@Gooey(use_events=[Events.ON_SUCCESS, Events.ON_ERROR])
def main():
...
Fortschritt und Zeitanzeige
- Gooey kann vorhandene textbasierte Fortschrittsausgabe lesen und damit eine Fortschrittsleiste steuern
- In einfachen Fällen wird ein String wie
Progress 83% per regulärem Ausdruck erkannt und in Fortschritt umgewandelt
@Gooey(progress_regex=r"^progress: (\\d+)%$")
- Komplexere Ausgaben lassen sich mit
progress_expr aus den Regex-Treffern umrechnen
@Gooey(progress_regex=r"^progress: (?P<current>\\d+)/(?P<total>\\d+)$",
progress_expr="current / total * 100")
- Mit
hide_progress_msg=True kann die zur Fortschrittsanzeige passende Textausgabe in der Konsole ausgeblendet werden
- Mit
timing_options lassen sich verstrichene Zeit und verbleibende Zeit anzeigen
- Die Zeitanzeige funktioniert nur, wenn
progress_regex und progress_expr verwendet werden
Icons und Packaging
- Gooey liefert sechs Standard-Icons mit, die durch Angabe eines benutzerdefinierten Bildverzeichnisses per Argument
image_dir überschrieben werden können
- Bilder werden anhand ihres Dateinamens gesucht; überschreibbar sind folgende Dateinamen
program_icon.png
success_icon.png
running_icon.png
loading_icon.gif
config_icon.png
error_icon.png
- Für das Packaging ausführbarer Dateien gibt es ein Beispiel mit PyInstaller
- Das Kurzverfahren besteht darin,
build.spec im Anwendungswurzelverzeichnis abzulegen, die Werte APPPNAME, name und pathex an das Projekt anzupassen und anschließend den Befehl auszuführen
pyinstaller -F --windowed build.spec
1 Kommentare
Hacker-News-Kommentare
Oh, das ist mein Projekt ^_^ Warum steht das ganz oben auf HN?
Um kurz auf die Kommentare zu
argparsezu antworten: Gooey ist inzwischen ein ziemlich altes Projekt, und als es begann, warargparseeine solide Wahl.Heutzutage funktioniert Gooey selbst über JSON und ist von
argparseentkoppelt, aber weil kaum jemand andere Interfaces gebaut hat, istargparseweiterhin das wichtigste „offizielle“ Interface.Interessanterweise kann es nicht nur Python, sondern auch beliebige ausführbare Dateien aufrufen, was ziemlich nützlich ist: https://chriskiehl.com/article/gooey-as-a-universal-frontend
Was die Aussage angeht, der letzte Commit sei 2 Jahre her: Wenn man älter wird und sich Prioritäten verschieben, wird es schwer, Gründe zu finden, Nischensoftware kostenlos weiter zu pflegen :( Falls es ein Trost ist: Ich habe deswegen immer ein schlechtes Gewissen.
Seltsamerweise gibt es überall in meiner Wohngegend „GOOEY“-Graffiti, die wie eine ständige Erinnerung an den vernachlässigten Issue-Tracker wirken, haha.
argparseist immer noch eine ziemlich gute Wahl. Es ist sehr weit verbreitet, gut dokumentiert und vergleichsweise einfach.Typer und Click sind ebenfalls gut benutzbar, aber bei Typers „Tutorial“-Dokumentation finde ich es ziemlich schwer, per Suche Antworten wie etwa darauf zu finden, welche Argumente
Typer.App()entgegennimmt.Das Programm, an dem ich gerade arbeite, ist so aufgebaut, dass Nutzer das Parsen der Argumente selbst starten, daher passt
argparsegut. Ich würde Nutzern gern eine textbasierte UI als Option anbieten, aber Textualize brauchte, glaube ich, Click, und selbst als ich versucht habe, mit Textual direkt im Code eine UI zu bauen, habe ich mehrere Stunden investiert und nicht einmal den Einstieg geschafft.Heutzutage gibt es so viele Ärgernisse, weil man Anwendungen nicht programmatisch steuern kann. Ehrlich gesagt wünschte ich, es gäbe ein Gesetz, dass jede Anwendungsfunktion eine API haben muss.
sys.argvin eine lokale Datei im aktuellen Arbeitsverzeichnis gedumpt? https://github.com/chriskiehl/Gooey/blob/be4b11b8f27f500e732...tmp.txtist alles andere als ein eindeutiger Name, daher frage ich mich, ob ich etwas übersehe.argparseentkoppelt“ ist großartig.Bevor ich nur anhand des Titels geklickt habe, dachte ich: „Das hängt bestimmt stark von
argparseab“, und wurde positiv überrascht.Ich bin ein begeisterter
getopt-Fan, weil ich Nutzerkomfort für viel wichtiger halte als Entwicklerkomfort. Nutzer sollten sich nicht darum kümmern müssen, welche Programmiersprache oder welche Options-Parsing-Bibliothek der Entwickler gewählt hat.argparse, Click, Gosflag/X11-Stil und viele andere Bibliotheken brechen mit Konventionen, die sich über ein halbes Jahrhundert in das kollektive Muskelgedächtnis eingebrannt haben. Aber mit einer Zwischenschicht scheint man beides zugleich erreichen zu können.Noch schlimmer ist, dass es auch keine tragfähige Alternative als Ersatz gibt und keiner der beiden Forks traction bekommen hat.
Sollte man das nicht auf „
argparse-basiert“ einschränken?argparseist für einfache Anwendungsfälle gut, aber es gibt auch viele Click-basierte CLIs, und ein beträchtlicher Teil der beliebten CLI-Bibliotheken baut auf Click auf. Es gibt auch Python-CLI-Tools, die wederargparsenoch Click verwenden, aber diese beiden sind vermutlich die beliebtesten.Ist bestätigt, dass es auch mit Click funktioniert? Im Moment sehe ich nur Inhalte zu
argparse. Wenn die Antwort nein ist, ist „fast alle“ offensichtlich falsch, und ein genauerer Titel wäre „Fast jedesargparse-basierte Python-Kommandozeilenprogramm in eine vollständige GUI-Anwendung verwandeln“.Dazu kommt, dass der letzte nennenswerte Commit mehr als 2 Jahre zurückliegt. Das ist an sich nicht schlimm, aber die Zahl der offenen Issues schafft nicht gerade großes Vertrauen in das Projekt.
Trotzdem ein cooles Projekt. Ich würde gern mehr davon sehen. Wie es im README heißt, ist es ein Werkzeug, das Hebelwirkung erzeugt, sodass jemand per CLI Automatisierung bauen und sie einfach mit nichttechnischen Büroangestellten teilen kann. Ähnlich wie Access es für Datenbanken getan hat.
Wie bei Access wird man bei zunehmender Größe oder Komplexität an Grenzen stoßen, aber für kleine Büroanwendungen kann es durchaus „gut genug“ sein.
argparsesiehst. Meine Neigung geht eher zu möglichst wenigen externen Abhängigkeiten.argparsenicht machen?Verwandte Beiträge:
Gooey: Turn almost any Python command line program into a GUI application - https://news.ycombinator.com/item?id=27490291 - Juni 2021, 115 Kommentare
Gooey: Turn command line programs into GUI applications - https://news.ycombinator.com/item?id=8218785 - August 2014, 74 Kommentare
Es wäre schön, wenn Betriebssysteme und Shells besser verstehen könnten, wie Programme ausgeführt werden sollen, ohne sich auf eine bestimmte Parsing-Bibliothek zu stützen.
Wenn Programme über typisierte JSON-/Proto-Formate kommunizieren würden und man allein durch Inspizieren der erwarteten Ein- und Ausgabetypen strukturierte Shell-Befehle, Autovervollständigung oder eine vollständige GUI bekommen könnte, wäre das ideal.
Im Moment wirkt es so, als sei das Beste, was wir haben, eine vorsichtig angeflanschte Lösung: Jedes Programm muss Autovervollständigungsdateien für mehrere Shells ausgeben, Flag-Stile unterscheiden sich je nach Programm und Parsing-Bibliothek stark, und eine GUI gibt es natürlich auch nicht.
Das Hauptproblem bei gRPC ist allerdings wohl, dass viele Entwickler, mich eingeschlossen, es im Vergleich zu Lösungen, die sich innerhalb der Sprache natürlich anfühlen, etwas umständlich finden.
Ich bin nicht sicher, ob PowerShell die statischen Typen, die den Kern bilden, vollständig ausnutzen kann, aber die Fähigkeit, auf der Kommandozeile Objekte hin und her zu reichen, ist nahezu einzigartig.
Unter Linux kann man
jc(https://github.com/kellyjonbrazil/jc) undjq(https://jqlang.github.io/jq/) kombinieren, um Kommandozeilen zu verketten, aber verglichen mit den eingebauten Fähigkeiten von PowerShell sind immer noch zwei zusätzliche Verarbeitungsschritte nötig.GUIs fühlen sich manchmal wie Comfort Food an. Man kann eine GUI-Oberfläche einfach erkunden, ohne die kognitive Last, die bei selten genutzten CLIs entstehen kann.
Etwas anderes Thema: Vor ein paar Monaten habe ich hier den Editor CUDATEXT kennengelernt; er erlaubt über eine Single-File-Python-API beliebige GUI-Elemente wie MENU oder INPUTS. Diese Elemente werden auch vom Editor selbst verwendet.
Inzwischen nutze ich solche einfachen GUI-Elemente für Einstellungen und generiere meinen Blog direkt im Editor.
Ebenfalls sehenswert:
„Textual: ein leichtgewichtiges Anwendungs-Framework für Python. Mit einer einfachen Python-API lassen sich ausgefeilte Benutzeroberflächen erstellen und Apps im Terminal und im Webbrowser ausführen“ https://github.com/textualize/textual/
camply: https://juftin.com/camply/
Ich möchte einfach Danke dafür sagen, dass ihr diese großartige Software gebaut habt. Ich mag Gooey und habe es in mehreren Programmen ausgiebig genutzt.
Für mich passt es perfekt in genau den Bereich, in dem ein Python-Skript etwas Wichtiges erledigt und nun auch für Nicht-Programmierer nutzbar gemacht werden muss.
Das erinnert mich an naked objects. Die Idee war, dass man bei Java-Klassen nur ein paar Annotationen und ein Theme definiert und daraus dann eine komplette GUI oder eine Web-Frontend-Anwendung erzeugt wird.
Eine sehr coole Idee, aber soweit ich weiß, hat es am Ende nicht wirklich funktioniert.
Meiner Meinung nach liegt das Problem darin, dass vertikale Belange wie Präsentation, Domäne und Infrastruktur miteinander gekoppelt werden. Solange die Bildschirmdarstellung und die Datenbankdarstellung des Domänenmodells einfach sind, ist das in Ordnung.
Wenn man aber eine komplexe Oberfläche mit vielen Komfortfunktionen bauen will, müssen diese Anforderungen in die Domänenschicht durchsickern. Umgekehrt ist es bei einem komplexen Domänenmodell unpraktisch, Invarianten auf Sprachebene zu erzwingen, weil jeder Code mit einer Referenz auf
Modelbeliebig daran herumändern kann.Schön wäre auch etwas, das den umgekehrten Weg geht.
argparsegewonnenen Informationen einen Parameter-Sweep konfigurieren und das Ganze dann wieder in ein Shell-Skript zurückverwandeln könnte, das die Läufe passend ausführt und die Ergebnisse speichert.Die alte Macintosh Programmer's Workshop, kurz MPW, eine textbasierte Shell für Mac OS aus den 80er- und 90er-Jahren, hatte für fast alle Befehle eine ähnliche Funktion namens Commando.
Die Commando-Informationen wurden in
cmdo-Ressourcen gespeichert. Wenn die Unterstützung für erweiterte Attribute nicht so uneinheitlich wäre, könnte man so etwas heute noch ähnlich umsetzen.Beim Nachsehen habe ich festgestellt, dass es Commando auch unter A/UX gab. Wenn man im Finder einen Terminalbefehl doppelt anklickte, erschien eine Commando-Box zur Auswahl der CLI-Optionen, danach wurde er in einem Shell-Fenster ausgeführt. Wenn man heute im Finder einen Terminalbefehl startet, wird er einfach ohne Argumente in einem Shell-Fenster ausgeführt.
https://cohost.org/boredzo/post/804893-i-still-want-a-moder
http://toastytech.com/guis/aux3.html