13. Édition interactive des entrées et substitution d’historique

Certaines versions de l’interpréteur Python prennent en charge l’édition de la ligne d’entrée courante et la substitution d’historique, similaires aux facilités que l’on trouve dans le shell Korn et dans le shell GNU Bash. C’est implémenté en utilisant la bibliothèque GNU Readline, qui supporte l’édition en style Emacs et en style Vi. La bibliothèque a sa propre documentation qui ne va pas être dupliquée ici ; toutefois, les bases seront expliquées rapidement. L’éditeur interactif et la gestion d’historique décrits ici sont disponibles en option sous les versions Unix et Cygwin de l’interpréteur.

Ce chapitre ne décrit pas les possibilités d’édition du paquet PythonWin de Mark Hammond ou de l’environnement basé sur Tk, IDLE, distribué avec Python. Le rappel d’historique des lignes de commandes qui fonctionne dans des fenêtres DOS sous NT ou d’autres variétés de Windows est encore une autre histoire.

13.1. Édition de ligne

Si elle est supportée, l’édition de la ligne d’entrée est active lorsque l’interpréteur affiche une invite primaire ou secondaire. La ligne courante peut être éditée en utilisant les caractères de contrôles traditionnels d’Emacs. Les plus importants d’entre eux sont : C-A (Contrôle-A) déplace le curseur au début de la ligne, C-E à la fin, C-B d’un caractère vers la gauche, C-F d’un caractère vers la droite. La touche retour arrière efface le caractère à la gauche du curseur, C-D le caractère à sa droite. C-K supprime le reste de la ligne à la droite du curseur, C-Y rappelle la dernière chaîne supprimée. C-tiret bas annule la dernière modification ; cette commande peut être répétée pour cumuler ses effets.

13.2. Substitution d’historique

La substitution d’historique fonctionne comme ceci. Toutes les lignes non vides reçues sont enregistrées dans un tampon d’historique et, à chaque fois qu’une invite est affichée, vous êtes positionné sur une nouvelle ligne à la fin de ce tampon. C-P remonte d’une ligne (en arrière) dans ce tampon, C-N descend d’une ligne. Chaque ligne présente dans le tampon d’historique peut être éditée ; un astérisque apparaît en face de l’invite pour indiquer qu’une ligne a été modifiée. Presser la touche Entrée envoie la ligne en cours à l’interpréteur. C-R démarre une recherche incrémentale en arrière ; C-S démarre une recherche en avant.

13.3. Raccourcis clavier

Les raccourcis clavier ainsi que d’autres paramètres de la bibliothèque Readline peuvent être personnalisés en inscrivant des commandes dans un fichier d’initialisation appelé ~/.inputrc. Les raccourcis sont de la forme

key-name: function-name

ou :

"string": function-name

et les options peuvent être définies avec

set option-name value

Par exemple :

# I prefer vi-style editing:
set editing-mode vi

# Edit using a single line:
set horizontal-scroll-mode On

# Rebind some keys:
Meta-h: backward-kill-word
"\C-u": universal-argument
"\C-x\C-r": re-read-init-file

Notez que le raccourci par défaut pour la touche Tab en Python est d’insérer un caractère de tabulation au lieu de la fonction par défaut de complétion des noms de fichiers de la bibliothèque Readline. Si vous y tenez, vous pouvez surcharger ce comportement en indiquant

Tab: complete

dans votre fichier ~/.inputrc (bien sûr, avec cela il devient plus difficile d’entrer des lignes de continuation indentées si vous êtes habitué à utiliser Tab dans ce but).

La complétude automatique des noms de variables et de modules est disponible de manière optionnelle. Pour l’activer dans le mode interactif de l’interpréteur, ajoutez les lignes suivantes à votre fichier de démarrage : [1]

import rlcompleter, readline
readline.parse_and_bind('tab: complete')

Ceci lie la touche Tab à la fonction de complétude, donc taper la touche Tab deux fois de suite suggère les options disponibles ; la recherche s’effectue dans les noms d’instructions Python, les noms des variables locales et les noms de modules disponibles. Pour les expressions pointées telles que string.a, l’expression est évaluée jusqu’au dernier '.' avant de suggérer les options disponibles à partir des attributs de l’objet résultant de cette évaluation. Notez bien que ceci peut exécuter une partie du code de l’application si un objet disposant d’une méthode __getattr__() fait partie de l’expression.

Un fichier de démarrage plus complet peut ressembler à cet exemple. Notez que celui-ci supprime les noms qu’il crée dès qu’ils ne sont plus nécessaires ; ceci est possible car le fichier de démarrage est exécuté dans le même espace de noms que les commandes interactives, et supprimer les noms évite de générer des effets de bord dans l’environnement interactif. Vous pouvez trouver pratique de conserver certains des modules importés, tels que os, qui s’avère nécessaire dans la plupart des sessions avec l’interpréteur.

# Add auto-completion and a stored history file of commands to your Python
# interactive interpreter. Requires Python 2.0+, readline. Autocomplete is
# bound to the Esc key by default (you can change it - see readline docs).
#
# Store the file in ~/.pystartup, and set an environment variable to point
# to it:  "export PYTHONSTARTUP=~/.pystartup" in bash.

import atexit
import os
import readline
import rlcompleter

historyPath = os.path.expanduser("~/.pyhistory")

def save_history(historyPath=historyPath):
    import readline
    readline.write_history_file(historyPath)

if os.path.exists(historyPath):
    readline.read_history_file(historyPath)

atexit.register(save_history)
del os, atexit, readline, rlcompleter, save_history, historyPath

13.4. Alternatives à l’interpréteur interactif

Cette facilité constitue un énorme pas en avant comparé aux versions précédentes de l’interpréteur ; toutefois, certains souhaits sont laissés de côté : ce serait bien si une indentation correcte était proposée sur les lignes de continuation (l’analyseur sait si une indentation doit suivre). Le mécanisme de complétion devrait utiliser la table de symboles de l’interpréteur. Une commande pour vérifier (ou même suggérer) les correspondances de parenthèses, de guillemets…, serait également utile.

Une alternative améliorée de l’interpréteur interactif qui a été développée depuis maintenant quelques temps est IPython, qui fournit la complétude, l’exploration d’objets et une gestion avancée de l’historique. Il peut également être personnalisé en profondeur et embarqué dans d’autres applications. Un autre environnement interactif amélioré similaire est bpython.

Notes

[1]Python exécute le contenu d’un fichier identifié par la variable d’environnement PYTHONSTARTUP lorsque vous démarrez un interpréteur interactif. Pour personnaliser Python y compris en mode non interactif, consultez Les modules de Personnalisation.