- Gooey transforme des applications console Python 3 en applications GUI faciles à utiliser pour les utilisateurs finaux, en ajoutant simplement une ligne de décorateur à une fonction contenant une déclaration
argparse
- L’installation de base se fait avec
pip install Gooey, et en utilisant le décorateur @Gooey avec ArgumentParser, Gooey lit les arguments et construit une interface basée sur des composants WX
- Quand la sélection de widgets par défaut ne suffit pas, on peut remplacer
ArgumentParser par GooeyParser et préciser l’argument widget pour choisir des widgets personnalisés comme FileChooser, DateChooser, PasswordField ou Slider
- Le public visé n’est pas tant les outils pour développeurs manipulant directement la CLI, mais plutôt les scripts bureautiques de type « exécuter puis terminé » ou les outils destinés à des non-programmeurs ; Gooey prend en charge les modes d’exécution avancé / basique / sans configuration, ainsi que les menus, l’affichage de progression, l’internationalisation, le changement d’icônes et le packaging
- La validation dynamique et les événements de cycle de vie sont indiqués comme des fonctions expérimentales ;
optparse n’est pas pris en charge actuellement, et l’outil part du principe d’un code basé sur ArgumentParser avec abonnement optionnel aux événements
Comment transformer un programme console en GUI
- Gooey convertit les applications console en applications GUI faciles à manipuler pour les utilisateurs finaux
- L’usage principal consiste à ajouter le décorateur
@Gooey à une fonction contenant une déclaration argparse
from gooey import Gooey
@Gooey
def main():
parser = ArgumentParser(...)
# rest of code
- Le style et le comportement peuvent être ajustés via les arguments du décorateur
advanced : afficher ou non l’écran de configuration avancée
language : choisir une traduction basée sur JSON
auto_start : ignorer l’écran de configuration et lancer immédiatement
target : définir la commande à exécuter dans un sous-processus
program_name, program_description : nom et description affichés dans la GUI
default_size : taille initiale de la GUI
dump_build_config, load_build_config : enregistrer / charger la configuration de build Gooey en JSON
monospace_display : utiliser une police à chasse fixe pour l’écran de sortie
Installation et exemples
- La méthode d’installation la plus simple est pip
pip install Gooey
- Il est aussi possible de cloner le dépôt puis d’installer via
setup.py
git clone https://github.com/chriskiehl/Gooey.git
python setup.py install
- Des scripts d’exemple prêts à l’emploi sont disponibles dans le dépôt Gooey Examples
- Ce dépôt d’exemples sert à parcourir différents layouts, widgets et fonctionnalités de Gooey
Pourquoi est-ce utile
- Gooey a été conçu pour réduire le problème consistant à exposer une invite de commande à des utilisateurs peu familiers avec celle-ci
- Lorsqu’un programme doit effectuer une ou plusieurs tâches, il a besoin d’options ; jusque-là, il fallait soit créer directement une GUI, soit expliquer comment passer des arguments à une application console
- Gooey permet aux développeurs de créer des programmes configurables avec des méthodes qui leur sont familières, tout en fournissant une interface GUI pour l’affichage et l’interaction
Utilisateurs adaptés et cas moins pertinents
- Gooey peut ne pas convenir aux utilitaires destinés à soi-même ou à d’autres programmeurs, ni aux outils produisant des résultats à chaîner vers d’autres applications console
- Il convient en revanche aux scripts bureautiques, aux outils de transfert de données d’un point A à un point B, et aux programmes destinés à des non-programmeurs
- L’objectif est de créer des applications complexes tout en obtenant la partie GUI sans coût supplémentaire
Fonctionnement interne et correspondance avec argparse
- Gooey analyse à l’exécution les références à
ArgumentParser dans le script Python
optparse n’est pas pris en charge actuellement
- Les arguments extraits se voient attribuer un type de composant en fonction de l’
action fournie, puis sont utilisés pour construire la GUI
ArgumentParser._actions est mappé par défaut vers les composants WX suivants
store : TextCtrl
store_const, store_true, store_False, version : CheckBox
append : TextCtrl
count : DropDown
Mutually Exclusive Group : RadioGroup
choice : DropDown
GooeyParser et widgets personnalisés
- Si la sélection de widgets par défaut ne suffit pas, on peut utiliser GooeyParser, un remplacement direct de
ArgumentParser
GooeyParser fournit un argument nommé supplémentaire, widget, qui permet de préciser le nom du composant à afficher
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")
- Les widgets personnalisés pris en charge incluent
DirChooser, FileChooser, MultiFileChooser
FileSaver, MultiFileSaver
DateChooser, TimeChooser
PasswordField
Listbox
BlockCheckbox
ColourChooser
FilterableDropdown
IntegerField, DecimalField
Slider
- Les valeurs transmises à l’application par
DateChooser et TimeChooser sont toujours au format ISO, même si certaines parties de la GUI peuvent afficher des valeurs localisées selon les paramètres de l’utilisateur final
BlockCheckbox déplace le bloc de texte à sa position normale quand le texte d’aide est long, pour une présentation plus claire qu’avec la case à cocher en ligne par défaut, et affiche un block_label court à côté du contrôle
Internationalisation
- Gooey sélectionne la langue d’affichage via l’argument
language du décorateur
@Gooey(language='russian')
def main():
...
- Tous les textes du programme sont stockés dans des fichiers JSON externes
- Pour ajouter une nouvelle langue, il faut ajouter des paires clé/valeur dans le répertoire
gooey/languages/
- Plus de 18 traductions sont actuellement fournies par défaut
Configuration globale et composition de l’interface
- L’apparence et le comportement globaux de Gooey se règlent via les arguments du décorateur
- Les principales options incluent
encoding : encodage des caractères affichés, utf-8 par défaut
advanced : choisir l’écran de configuration complet ou une vue simplifiée
auto_start : lancer immédiatement sans configuration
target : définir comment Gooey se relance lui-même
suppress_gooey_flag : empêcher l’injection de paramètres CLI supplémentaires lors de l’utilisation d’un target personnalisé
fullscreen : démarrer en plein écran
image_dir : répertoire d’images / d’icônes personnalisées
language_dir : répertoire de fichiers de langue personnalisés
disable_stop_button, show_stop_warning : contrôler le bouton d’arrêt et l’avertissement pendant l’exécution
show_success_modal, show_failure_modal : afficher ou non des fenêtres récapitulatives de succès / d’échec
run_validators : exécuter les validations avant l’appel du programme
progress_regex, progress_expr : analyser et convertir le texte de progression
navigation : TABBED ou SIDEBAR
body_bg_color, header_bg_color, footer_bg_color, sidebar_bg_color : configuration des couleurs
terminal_font_family, terminal_font_size, terminal_font_color : réglages de police pour l’affichage terminal
menus : groupes et éléments de menu personnalisés
clear_before_run : effacer la sortie précédente lors d’une nouvelle exécution
Layouts et modes d’exécution
- Gooey répartit par défaut les entrées en deux groupes :
positional et optional
- Avec
add_argument_group() d’argparse, on peut regrouper les entrées de façon logique et ajuster le layout de chaque groupe
parser = ArgumentParser()
search_group = parser.add_argument_group(
"Search Options",
"Customize the search options"
)
search_group.add_argument(
'--query',
help='Base search string'
)
Fonctionnalités de menu
- Depuis Gooey 1.0.2, on peut ajouter une barre de menu en haut de la fenêtre
- Les menus se définissent sous la forme
@Gooey(menu=[{}, {}, ...]), c’est-à-dire une liste de maps
- Chaque groupe de menu possède
name et items
- Chaque élément de menu contient toujours
type et menuTitle
- Les types d’éléments de menu pris en charge sont
AboutDialog : afficher les informations sur le programme, comme le nom, la version ou la licence
MessageDialog : afficher un message informatif à l’utilisateur
Link : ouvrir l’URL indiquée dans le navigateur par défaut
HtmlDialog : afficher une boîte de dialogue à partir d’un sous-ensemble limité de HTML
Validation dynamique
- Dynamic Validation est une fonctionnalité expérimentale dont l’API peut changer ou être supprimée
- Gooey peut éventuellement effectuer une validation préalable des saisies utilisateur avant de les transmettre au programme
- Cette fonctionnalité exploite le paramètre
type, utilisable avec la plupart des types d’arguments Argparse
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!")
- La validation n’est pas exécutée par défaut
- Pour l’activer, il faut s’abonner à l’événement
VALIDATE_FORM
from gooey import Gooey, Events
@Gooey(use_events=[Events.VALIDATE_FORM])
def main():
...
- Cette fonctionnalité repose en interne sur un monkey patching important, ce qui explique son caractère actuellement opt-in
Événements de cycle de vie et contrôle de l’interface
- Depuis Gooey 1.2.0, le programme expose des hooks de cycle de vie
- Cette fonctionnalité est elle aussi expérimentale, et son API peut changer ou être supprimée
- Il existe actuellement deux hooks principaux
- Ces deux hooks sont exécutés une fois le processus terminé
- Les handlers reçoivent l’objet Argparse parsé et l’état courant de la GUI Gooey ; s’ils renvoient un état mis à jour, celui-ci peut être répercuté dans l’interface
- Les handlers se connectent lors de la création du
GooeyParser
parser = GooeyParser(
on_success=my_success_handler,
on_failure=my_failure_handler)
- Pour les utiliser, il faut s’abonner explicitement aux événements
from gooey import Gooey, Events
@Gooey(use_events=[Events.ON_SUCCESS, Events.ON_ERROR])
def main():
...
Progression et affichage du temps
- Gooey peut lire une sortie texte de progression existante pour piloter une barre de progression
- Dans les cas simples, une chaîne comme
Progress 83% peut être reconnue via une expression régulière puis convertie en progression
@Gooey(progress_regex=r"^progress: (\d+)%$")
- Pour des sorties plus complexes,
progress_expr permet de transformer les résultats de la regex
@Gooey(progress_regex=r"^progress: (?P<current>\d+)/(?P<total>\d+)$",
progress_expr="current / total * 100")
- Si
hide_progress_msg=True est spécifié, la sortie texte correspondant à la progression peut être masquée dans la console
timing_options permet d’afficher le temps écoulé et le temps restant
- L’affichage du temps ne fonctionne que lors de l’utilisation de
progress_regex et progress_expr
Icônes et packaging
- Gooey fournit six icônes par défaut, que l’on peut remplacer en définissant un répertoire d’images personnalisé via l’argument
image_dir
- Les images sont recherchées par nom de fichier, et les noms remplaçables sont les suivants
program_icon.png
success_icon.png
running_icon.png
loading_icon.gif
config_icon.png
error_icon.png
- Un exemple de packaging d’exécutable avec PyInstaller est fourni
- La procédure résumée consiste à placer
build.spec à la racine de l’application, à adapter APPPNAME, name et pathex au projet, puis à exécuter la commande suivante
pyinstaller -F --windowed build.spec
1 commentaires
Avis sur Hacker News
Euh, c’est mon projet ^_^ Pourquoi est-il en haut de HN ?
Pour répondre brièvement aux commentaires sur
argparse: Gooey est désormais un projet assez ancien, et au moment où il a commencé,argparseétait un choix solide.Aujourd’hui, Gooey lui-même fonctionne avec du JSON et est découplé d’
argparse, mais comme presque personne n’a créé d’autres interfaces,argparsereste encore l’interface « officielle » principale.Détail amusant : il peut appeler non seulement Python, mais aussi n’importe quel exécutable, ce qui le rend assez utile : https://chriskiehl.com/article/gooey-as-a-universal-frontend
Quant au fait que le dernier commit remonte à deux ans, quand on vieillit et que les priorités changent, il devient difficile de trouver une raison de continuer à maintenir gratuitement un logiciel de niche :( Je ne sais pas si c’est consolant, mais je me sens toujours coupable.
Étrangement, il y a des graffitis « GOOEY » un peu partout dans mon quartier, ce qui fait comme un rappel permanent de l’issue tracker laissé à l’abandon, haha.
argparsereste un très bon choix. Il est extrêmement répandu, bien documenté et relativement simple.Typer et Click sont aussi agréables à utiliser, mais je trouve que la documentation façon « tutoriel » de Typer est assez difficile à parcourir quand on cherche une réponse du genre : quels arguments prend
Typer.App()?Le programme sur lequel je travaille en ce moment a une structure où l’utilisateur lance lui-même le parsing des arguments, donc
argparseconvient bien. J’aimerais proposer aux utilisateurs une UI en mode texte, mais il me semble que Textualize nécessitait Click, et même en essayant de brancher directement Textual dans le code pour créer l’UI, j’y ai passé des heures sans même réussir à démarrer.Il y a aujourd’hui trop de frustrations dues au fait qu’on ne peut pas contrôler les applications par programmation. Honnêtement, j’aimerais qu’il existe une loi imposant une API pour toutes les fonctionnalités d’une application.
sys.argvdans un fichier local du répertoire de travail courant ? https://github.com/chriskiehl/Gooey/blob/be4b11b8f27f500e732...tmp.txtest loin d’être un nom unique ; je me demande si quelque chose m’échappe.argparse» est excellente.Avant de cliquer, rien qu’au titre, je me disais : « ça va forcément être fortement dépendant d’
argparse», et j’ai été agréablement surpris.Je suis un fervent fan de
getopt, parce que je considère que le confort de l’utilisateur est bien plus important que celui du développeur. L’utilisateur ne devrait pas avoir à se soucier du langage de programmation ou de la bibliothèque de parsing d’options choisis par le développeur.argparse, Click, leflagde Go / le style X11 et beaucoup d’autres bibliothèques cassent des conventions ancrées dans un demi-siècle de mémoire musculaire collective. Mais avec une couche intermédiaire, on dirait qu’on peut avoir le beurre et l’argent du beurre.Le pire, c’est qu’aucune alternative viable n’a émergé pour le remplacer, et qu’aucun des deux forks n’a vraiment gagné en traction.
Est-ce qu’il ne faudrait pas préciser « basé sur
argparse» ?argparseest bien pour les usages simples, mais il existe aussi beaucoup de CLI basées sur Click, et une bonne partie des bibliothèques CLI populaires sont construites au-dessus de Click. Il existe aussi des outils CLI Python qui ne sont niargparseni Click, même si ces deux-là sont probablement parmi les plus populaires.A-t-on vérifié que ça fonctionne aussi avec Click ? Pour l’instant, je ne vois que des éléments liés à
argparse. Si la réponse est non, l’expression « presque tous » est manifestement fausse, et un titre plus exact serait « Transformer presque tous les programmes Python en ligne de commande basés surargparseen applications GUI complètes ».Il y a aussi le fait que le dernier commit significatif remonte à plus de deux ans. Ce n’est pas mauvais en soi, mais vu le nombre d’issues ouvertes, ça ne donne pas énormément confiance dans le projet.
Cela dit, c’est un beau projet. J’aimerais voir davantage de choses comme ça. Comme le dit le README, c’est un outil démultiplicateur de force : quelqu’un peut créer une automatisation en CLI et la partager facilement avec des personnes non techniques dans un bureau. C’est un peu le rôle qu’Access a joué pour les bases de données.
Comme avec Access, dès qu’il y aura de l’échelle ou de la complexité, on atteindra ses limites, mais pour de petits usages de bureau, cela peut être « suffisamment bon ».
argparse. De mon côté, j’ai plutôt tendance à minimiser les dépendances externes.argparse?Articles liés :
Gooey: Turn almost any Python command line program into a GUI application - https://news.ycombinator.com/item?id=27490291 - juin 2021, 115 commentaires
Gooey: Turn command line programs into GUI applications - https://news.ycombinator.com/item?id=8218785 - août 2014, 74 commentaires
Ce serait bien que les systèmes d’exploitation et les shells puissent mieux comprendre la façon dont les programmes s’exécutent, sans dépendre d’une bibliothèque de parsing particulière
Ce serait bien que les programmes communiquent dans un format JSON/proto typé, et qu’en inspectant simplement les types d’entrée et de sortie attendus, on puisse obtenir une structuration et de l’autocomplétion des commandes shell, voire une GUI complète
Pour l’instant, le mieux qu’on semble pouvoir faire ressemble à quelque chose bricolé prudemment à la paille. Chaque programme doit exporter des fichiers d’autocomplétion pour plusieurs shells, les styles de flags varient fortement selon les programmes et les bibliothèques de parsing, et bien sûr il n’y a pas de GUI
Cela dit, le principal problème de gRPC est sans doute que beaucoup de développeurs, moi y compris, le trouvent un peu plus lourd à manier que les solutions qu’on utilise naturellement dans un langage
Je ne sais pas si PowerShell peut exploiter pleinement le typage statique qui en constitue le cœur, mais sa capacité à faire circuler des objets en ligne de commande est presque unique
Sous Linux, on peut chaîner des commandes en combinant
jc(https://github.com/kellyjonbrazil/jc) etjq(https://jqlang.github.io/jq/), mais cela demande encore deux étapes de traitement de plus par rapport aux fonctionnalités intégrées de PowerShellUne GUI, c’est parfois comme de la comfort food. On peut simplement parcourir une interface graphique, sans la charge cognitive que peut imposer une CLI qu’on utilise rarement
C’est un peu à côté, mais j’ai découvert ici l’éditeur CUDATEXT il y a quelques mois ; il permet d’utiliser, via une API Python dans un seul fichier, des éléments de GUI arbitraires comme MENU ou INPUTS. Ce sont les mêmes éléments que ceux utilisés par l’éditeur lui-même
Désormais, j’utilise ces éléments graphiques simples pour configurer des choses et générer mon blog directement dans l’éditeur
À voir aussi :
« Textual : un framework d’application léger pour Python. Créez des interfaces utilisateur sophistiquées avec une API Python simple, et exécutez vos apps dans le terminal et dans un navigateur web » https://github.com/textualize/textual/
camply : https://juftin.com/camply/
Je voulais dire merci d’avoir créé cet excellent logiciel. J’aime Gooey et je l’ai beaucoup utilisé dans plusieurs programmes
Pour moi, il correspond parfaitement à ce cas précis où un script Python fait quelque chose d’important, et où il faut maintenant le rendre utilisable par des non-programmeurs
Ça me fait penser aux naked objects. L’idée était qu’en définissant quelques annotations et un thème sur des classes Java, on générait une GUI complète, ou une application web front-end
C’était une idée très élégante, mais à ma connaissance elle n’a finalement pas vraiment pris
À mon avis, le problème est que des préoccupations verticales comme la présentation, le domaine et l’infrastructure se retrouvent couplées. Quand la représentation visuelle et la représentation en base de données du modèle de domaine sont simples, ça va
Mais si l’on veut construire une interface complexe avec beaucoup de fonctionnalités de confort, ces exigences doivent fuiter dans la couche domaine. À l’inverse, si l’on veut construire un modèle de domaine complexe, il devient irréaliste d’imposer les invariants au niveau du langage, car n’importe quel code ayant une référence vers
Modelpeut le modifier arbitrairementCe serait bien d’avoir aussi l’inverse
argparse, puis de le reconvertir en script shell qui exécute et enregistre correctement les résultatsDans l’ancien Macintosh Programmer's Workshop, ou MPW, le shell textuel de Mac OS dans les années 80 et 90, il existait une fonctionnalité similaire appelée Commando pour presque toutes les commandes
Les informations de Commando étaient stockées dans des ressources
cmdo. Si la prise en charge des attributs étendus n’avait pas été aussi inégale, on pourrait encore faire quelque chose de similaire aujourd’huiEn cherchant, j’ai vu qu’A/UX avait aussi Commando. Quand on double-cliquait sur une commande de terminal dans le Finder, une boîte Commando permettant de choisir les options CLI s’ouvrait, puis la commande s’exécutait dans une fenêtre shell. Aujourd’hui, quand on lance une commande de terminal depuis le Finder, elle s’exécute simplement dans une fenêtre shell, sans argument
https://cohost.org/boredzo/post/804893-i-still-want-a-moder
http://toastytech.com/guis/aux3.html