Maîtriser IPython : Un Guide Complet pour l'Interpréteur Amélioré de Python

Démarré en 2001 par Fernando Perez, le projet IPython visait à créer un environnement Python interactif plus puissant. Il a évolué pour devenir bien plus qu'une simple amélioration du shell Python standard. IPython offre une console graphique pour le traçage, un environnement de calcul interactif basé sur le web (le précurseur de Jupyter Notebook), et un moteur léger pour le calcul parallèle rapide.

En tant qu'outil de ligne de commande Python interactif modernisé, ipython remplace l'invite standard de Python par des indications In et Out distinctes, signalant clairement les entrées de commande et les résultats d'exécution.

Installation d'IPython

Installation dans un environnement Python existant

Si Python est déjà installé sur votre système, vous pouvez installer IPython via pip :

pip install ipython

Une fois l'installation terminée, un message de succès s'affichera. Vous pouvez ensuite lancer IPython en tapant ipython dans votre terminal.

L'interface d'IPython se distingue par ses invites In [n]: pour l'entrée et Out[n]: pour la sortie des commandes, où n est un numéro de séquence.

Fonctionnalités Clés d'IPython

Autocomplétion via la touche Tab

IPython améliore considérablement la productivité grâce à son autocomplétion intelligente. En tapant une partie d'un nom de variable, de fonction ou de module, puis en appuyant sur la touche Tab, IPython propose des complétions possibles.

Exécution de Comandes Système

IPython permet d'exécuter directement des commandes du système d'exploitation. Certaines commandes courantes sont même prises en charge nativement sans préfixe, tandis que d'autres nécessitent le préfixe !.

Commandes système intégrées

In [1]: pwd           # Affiche le répertoire de travail actuel
Out[1]: '/home/utilisateur'

In [2]: cd ..         # Remonte d'un répertoire
/

Exécution de commandes shell avec '!'

Pour exécuter n'importe quelle commande shell, il suffit de la préfixer avec un point d'exclamation ! :

In [3]: !ls -lha
total 48K
drwxr-xr-x  5 utilisateur groupe 4,0K déc 14 10:30 .
drwxr-xr-x 19 root        root   4,0K déc 13 16:20 ..
-rw-r--r--  1 utilisateur groupe  12K jan 20 2023  mon_script.py
... (autres fichiers et répertoires)

In [4]: output = !echo "Bonjour depuis IPython"
In [5]: print(output)
['Bonjour depuis IPython']

Introspection d'Objets avec '?'

Le mécanisme d'introspection d'IPython, accessible en ajoutant un point d'interrogation ? avant ou après un nom de variable, fonction ou module, fournit des informations détaillées sur l'objet, telles que son type, sa docstring et sa signature.

In [1]: ma_chaine = "Exemple de texte"

In [2]: ma_chaine.upper?
Type:        builtin_function_or_method
String form: <built-in at="" method="" object="" of="" str="" upper="">
Docstring:   S.upper() -> str

             Return a copy of S converted to uppercase.
</built-in>

L'utilisation de deux points d'interrogation ?? tente d'afficher le code source de l'objet, si celui-ci est disponible.

Raccourcis Clavier Essentiels

IPython intègre une série de raccourcis clavier pour naviguer et manipuler le texte dans la console :

  • Ctrl-P ou Flèche Haut : Recherche les commandes précédentes dans l'historique.
  • Ctrl-N ou Flèche Bas : Recherche les commandes suivantes dans l'historique.
  • Ctrl-R : Recherche inversée incrémentale dans l'historique des commandes.
  • Ctrl-Shift-V : Colle le texte du presse-papiers.
  • Ctrl-C : Interrompt l'exécution de la commande en cours.
  • Ctrl-A : Déplace le curseur au début de la ligne.
  • Ctrl-E : Déplace le curseur à la fin de la ligne.
  • Ctrl-K : Supprime le texte depuis le curseur jusqu'à la fin de la ligne.
  • Ctrl-U : Efface tout le texte sur la ligne actuelle.
  • Ctrl-F : Déplace le curseur d'un caractère vers l'avant.
  • Ctrl-B : Déplace le curseur d'un caractère vers l'arrière.
  • Ctrl-L : Efface l'écran de la console.

Commandes Magiques (Magic Commands)

Les commandes magiques d'IPython, préfixées par un %, étendent les capacités du shell en permettant des opérations spécifiques non disponibles directement en Python. Une commande magique à double pourcentage %% s'applique à toute une cellule de code.

Voici quelques commandes magiques courantes :

  • %quickref : Affiche une référence rapide d'IPython.
  • %magic : Affiche la documentation détaillée de toutes les commandes magiques.
  • %debug : Démarre le débogueur interactif après la dernière exception.
  • %hist : Affiche l'historique des commandes (entrées et sorties).
  • %paste : Exécute le code Python contenu dans le presse-papiers.
  • %reset : Supprime toutes les variables/noms de l'espace de noms interactif.
  • %run script.py : Exécute un script Python dans IPython.
  • %time statement : Mesure le temps d'exécution d'une instruction.
  • %timeit statement : Exécute une instruction plusieurs fois pour une mesure précise du temps moyen.
  • %whos : Liste les variables définies dans l'espace de noms, avec leur type.
  • %xdel variable : Supprime une variable et tente de libérer toutes les références à son objet.

Pour explorer les commandes magiques, utilisez %magic ou %cmd? pour la documentation spécifique d'une commande.

Mesure du temps d'exécution : %time et %timeit

Ces commandes sont cruciales pour profiler de petites sections de codee :

In [1]: def calculer_carres(n):
   ...:     return [x*x for x in range(n)]
   ...:

In [2]: %time resultat = calculer_carres(10000)
CPU times: user 1.34 ms, sys: 12 µs, total: 1.35 ms
Wall time: 1.35 ms

In [3]: %timeit resultat = calculer_carres(10000)
1.25 ms ± 15.6 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

Système de marque-pages de répertoires

IPython permet de créer des alias pour des chemins de répertoires, simplifiant la navigation :

In [4]: %bookmark mon_projet /chemin/vers/mon/projet
In [5]: %bookmark config_app /etc/application/config

In [6]: %bookmark -l       # Liste tous les marque-pages
Current bookmarks:
config_app -> /etc/application/config
mon_projet -> /chemin/vers/mon/projet

In [7]: pwd
Out[7]: '/'

In [8]: cd mon_projet
(bookmark:mon_projet) -> /chemin/vers/mon/projet
/chemin/vers/mon/projet

In [9]: cd config_app
(bookmark:config_app) -> /etc/application/config
/etc/application/config

Journalisation de l'historique

La commande %logstart permet d'enregistrer toutes les entrées et sorties de la session IPython dans un fichier. D'autres commandes comme %logoff, %logon, %logstate et %logstop gèrent ce processus.

Interaction avec le système d'exploitation

IPython fournit plusieurs commandes magiques pour interagir avec l'environnement système :

Commande Description
!cmd Exécute cmd dans le shell système.
output=!cmd args Exécute cmd et stocke la sortie standard dans output.
%alias alias_name cmd Définit un alias pour une commande shell.
%bookmark Utilise le système de marque-pages de répertoires d'IPython.
%cd directory Change le répertoire de travail actuel.
%pwd Affiche le répertoire de travail actuel.
%pushd directory Pousse le répertoire actuel sur une pile et se déplace vers directory.
%popd Fait sortir le répertoire du haut de la pile et s'y déplace.
%dirs Affiche la pile des répertoires.
%dhist Affiche l'historique des changements de répertoire.
%env Affiche les variables d'environnement système sous forme de dictionnaire.

IPython Notebook (Jupyter)

Le projet IPython Notebook est le prédécesseur direct de Jupyter Notebook. Pour utiliser cette interface web interactive, vous devez installer Jupyter :

pip install jupyter

Après l'installation, lancez jupyter notebook pour ouvrir l'interface dans votre navigateur.

Utilisation Avancée d'IPython

Alias Personnalisés

Vous pouvez définir des alias pour des commandes shell complexes, y compris celles avec des paramètres :

In [1]: %alias afficher_details ls -lha | grep %s
In [2]: afficher_details .txt
-rw-r--r-- 1 utilisateur groupe 12K jan 20 2023  fichier_log.txt
-rw-r--r-- 1 utilisateur groupe  8K fév 15 2023  rapport.txt

Pour que les alias soient persistants au-delà de la session actuelle, utilisez la commande %store :

In [3]: %store afficher_details
Alias stored: afficher_details (ls -lha | grep %s)

Lors d'une nouvelle session, restaurez-les avec %store -r.

ipcluster - Calcul Parallèle

IPython offre des capacités de calcul parallèle via ipcluster. Commencez par lancer des moteurs parallèles :

ipcluster start -n 4 # Lance 4 moteurs IPython pour le calcul parallèle

Exemple de Comptage de Mots Parallélisé

Considérons un fichier texte volumineux, par exemple mon_grand_texte.txt, et nous voulons compter la fréquence des mots.

D'abord, les fonctions de traitement de texte de base :

import re
import io
from collections import defaultdict

# Motif pour les caractères spéciaux (non-mots)
special_chars_pattern = re.compile(r'[\W\d_]+', re.UNICODE)

# Liste de mots fréquents à ignorer
frequent_words = {
    'le', 'la', 'les', 'un', 'une', 'des', 'de', 'du', 'd', 'et', 'à', 'est',
    'il', 'elle', 'on', 'nous', 'vous', 'ils', 'elles', 'ce', 'cet', 'cette',
    'ces', 'que', 'qui', 'quoi', 'où', 'quand', 'comment', 'pour', 'par',
    'avec', 'sur', 'dans', 'en', 'mais', 'ou', 'ni', 'car', 'donc', 'or',
    'si', 'comme', 'quand', 'lorsque', 'tandis', 'aussi', 'ainsi', 'alors',
    'après', 'avant', 'depuis', 'pendant', 'toujours', 'jamais', 'souvent',
    'rarement', 'très', 'plus', 'moins', 'peu', 'beaucoup', 'tout', 'toute',
    'tous', 'toutes', 'même', 'autres', 'chaque', 'quelques', 'plusieurs',
    'certains', 'certaines', 'chaque', 'chacun', 'chacune', 'y', 'en', 'ne', 'pas',
    'plus', 'rien', 'mon', 'ma', 'mes', 'ton', 'ta', 'tes', 'son', 'sa', 'ses',
    'notre', 'nos', 'votre', 'vos', 'leur', 'leurs'
}

def extract_words_from_file(file_path):
    """Générateur qui extrait et nettoie les mots d'un fichier."""
    with io.open(file_path, encoding='utf-8', errors='ignore') as f:
        for line_content in f:
            for raw_word in line_content.split():
                clean_word = special_chars_pattern.sub('', raw_word.lower())
                if clean_word and clean_word not in frequent_words:
                    yield clean_word

def perform_word_count(file_path):
    """Compte la fréquence des mots dans un fichier donné."""
    word_counts = defaultdict(int)
    for word_token in extract_words_from_file(file_path):
        word_counts[word_token] += 1
    return word_counts

# Exemple d'exécution séquentielle
# %time total_counts_seq = perform_word_count('mon_grand_texte.txt')

Maintenant, l'approche parallèle avec IPython.parallel :

from IPython import parallel

# 1. Connexion au client IPython parallèle
client = parallel.Client()
engine_ids = client.ids  # IDs des moteurs disponibles
print(f"Moteurs IPython disponibles: {engine_ids}")

# Création d'une vue load-balanced
view_lb = client.load_balanced_view()

# 2. Diffusion des fonctions et données nécessaires aux moteurs
# Utilisez 'push' pour envoyer des variables aux moteurs
client[:].push(dict(
    special_chars_pattern=special_chars_pattern,
    frequent_words=frequent_words,
    extract_words_from_file=extract_words_from_file,
    perform_word_count=perform_word_count,
    defaultdict=defaultdict, # defaultdict doit aussi être poussé
    re=re, # et le module re
    io=io # et le module io
))

# 3. Fonction pour diviser le fichier en morceaux plus petits
import os

def split_text_into_chunks(original_filename, num_chunks=len(engine_ids)):
    """Divise un fichier texte en plusieurs sous-fichiers pour le traitement parallèle."""
    with open(original_filename, 'r', encoding='utf-8', errors='ignore') as f_orig:
        all_lines = f_orig.readlines()

    total_lines = len(all_lines)
    chunk_size = total_lines // num_chunks
    chunk_filenames = []
    current_dir = os.path.abspath(os.getcwd())

    for i in range(num_chunks):
        start_line = i * chunk_size
        end_line = (i + 1) * chunk_size if i < num_chunks - 1 else total_lines
        chunk_content = "".join(all_lines[start_line:end_line])
        
        chunk_file_path = os.path.join(current_dir, f"chunk_{i}.txt")
        with open(chunk_file_path, 'w', encoding='utf-8') as f_chunk:
            f_chunk.write(chunk_content)
        chunk_filenames.append(chunk_file_path)
    
    return chunk_filenames

# Créez un fichier bidon pour l'exemple si mon_grand_texte.txt n'existe pas
if not os.path.exists('mon_grand_texte.txt'):
    with open('mon_grand_texte.txt', 'w', encoding='utf-8') as f:
        for _ in range(10000): # 10000 lignes
            f.write("Ceci est un exemple de ligne de texte pour le comptage de mots. " * 10 + "\n")

chunk_files = split_text_into_chunks('mon_grand_texte.txt')
print(f"Fichiers de fragments créés: {chunk_files}")

# 4. Exécution parallèle et agrégation des résultats
def aggregate_parallel_counts():
    """Exécute le comptage de mots en parallèle et aggrège les résultats."""
    # map envoie la fonction perform_word_count à chaque moteur avec un fichier de fragment
    async_results = view_lb.map(perform_word_count, chunk_files)
    
    # Attend que tous les résultats soient prêts et les récupère
    list_of_partial_counts = async_results.get()

    final_word_counts = defaultdict(int)
    for partial_counts in list_of_partial_counts:
        for word, count in partial_counts.items():
            final_word_counts[word] += count
    
    return final_word_counts, async_results

# Mesure le temps d'exécution parallèle
print("\nDébut du comptage de mots parallèle...")
%time final_counts_parallel, parallel_res = aggregate_parallel_counts()

print(f"\nTemps écoulé pour la carte parallèle: {parallel_res.elapsed:.4f} secondes")
# print(f"Quelques mots et leurs fréquences: {list(final_counts_parallel.items())[:5]}")

# Nettoyage des fichiers de fragments
for f_path in chunk_files:
    os.remove(f_path)

Étiquettes: IPython Python Shell Jupyter Parallélisation

Publié le 17 juin à 01h58