Ecrire les messages d'erreur sur la sortie d'erreur standard au lieu de la sortie normale
Pour l'instant, nous avons écrit toutes nos sorties du terminal en utilisant
la macro println!
. Dans la plupart des terminaux, il y a deux genres de
sorties : la sortie standard (stdout
) pour les informations générales
et la sortie d'erreur standard (stderr
) pour les messages d'erreur. Cette
distinction permet à l'utilisateur de choisir de rediriger la sortie des
messages sans erreurs d'un programme vers un fichier mais continuer à afficher
les messages d'erreur à l'écran.
La macro println!
ne peut écrire que sur la sortie standard, donc nous
devons utiliser autre chose pour écrire sur la sortie d'erreur standard.
Vérifier où sont écrites les erreurs
Commençons par observer comment le contenu écrit par minigrep
est actuellement
écrit sur la sortie standard, y compris les messages d'erreur que nous
souhaitons plutôt écrire sur la sortie d'erreur standard. Nous allons faire cela
en redirigeant le flux de sortie standard vers un fichier pendant que nous
déclencherons intentionnellement une erreur. Nous ne redirigerons pas le flux
de sortie d'erreur standard, si bien que n'importe quel contenu envoyé à la sortie
d'erreur standard va continuer à s'afficher à l'écran.
Les programmes en ligne de commande sont censés envoyer leurs messages d'erreur dans le flux d'erreurs standard afin que nous puissions continuer à voir les messages d'erreurs à l'écran même si nous redirigeons le flux de la sortie standard dans un fichier. Notre programme ne se comporte pas comme il le devrait : nous allons voir qu'à la place, il envoie les messages d'erreur dans le fichier !
Pour démontrer ce comportement, il faut exécuter le programme avec >
suivi du
nom du fichier, sortie.txt, dans lequel nous souhaitons rediriger le flux de
sortie standard. Nous ne fournissons aucun argument, ce qui va causer une
erreur :
$ cargo run > sortie.txt
La syntaxe indique à l'invite de commande d'écrire le contenu de la sortie standard dans sortie.txt plutôt qu'à l'écran. Nous n'avons pas vu le message d'erreur que nous nous attendions de voir à l'écran, ce qui veut dire qu'il a dû finir dans le fichier. Voici ce que sortie.txt contient :
Problème rencontré lors de l'interprétation des arguments : il n'y a pas assez d'arguments
Effectivement, notre message d'erreur est écrit sur la sortie standard. Il serait bien plus utile que les messages d'erreur comme celui-ci soient écrits sur la sortie d'erreur standard afin que seules les données produites par exécution fructueuse finissent dans le fichier. Nous allons corriger cela.
Ecrire les erreurs sur la sortie d'erreur standard
Nous allons utiliser le code de l'encart 12-24 pour changer la manière dont les
messages d'erreur sont écrits. Grâce au remaniement que nous avons fait plus tôt
dans ce chapitre, tout le code qui écrit les messages d'erreurs se trouve dans
une seule fonction, main
. La bibliothèque standard fournit la macro
eprintln!
qui écrit dans le flux d'erreur standard, donc changeons les deux
endroits où nous appelons println!
afin d'utiliser eprintln!
à la place.
Fichier : src/main.rs
use std::env;
use std::process;
use minigrep::Config;
fn main() {
let args: Vec<String> = env::args().collect();
let config = Config::new(&args).unwrap_or_else(|err| {
eprintln!("Problème rencontré lors de l'interprétation des arguments : {}", err);
process::exit(1);
});
if let Err(e) = minigrep::run(config) {
eprintln!("Erreur applicative : {}", e);
process::exit(1);
}
}
Après avoir changé println!
en eprintln!
, exécutons à nouveau le programme
de la même manière, sans aucun argument et en redirigeant la sortie standard
avec >
:
$ cargo run > sortie.txt
Problème rencontré lors de l'interprétation des arguments : il n'y a pas assez d'arguments
Désormais nous pouvons voir l'erreur à l'écran et sortie.txt ne contient rien, ce qui est le comportement que nous attendons d'un programme en ligne de commande.
Exécutons le programme à nouveau avec des arguments qui ne causent pas d'erreur tout en continuant à rediriger la sortie standard vers un fichier, comme ceci :
$ cargo run to poem.txt > sortie.txt
Nous ne voyons rien sur la sortie du terminal, et sortie.txt devrait contenir notre résultat :
Fichier : sortie.txt
Are you nobody, too?
How dreary to be somebody!
Ceci prouve qu'en fonction des circonstances, nous utilisons maintenant la sortie standard pour la sortie sans les erreurs et l'erreur standard pour la sortie d'erreur.
Résumé
Ce chapitre a résumé certains des concepts majeurs que vous avez appris
précédemment et expliqué comment procéder à des opérations courantes sur les
entrées/sorties en Rust. En utilisant les arguments en ligne de commande, les
fichiers, les variables d'environnement et la macro eprintln!
pour écrire les
erreurs, vous pouvez désormais écrire des applications en ligne de commande. En
suivant les concepts vus dans les chapitres précédents, votre code restera bien
organisé, stockera les données dans les bonnes structures de données, gérera
correctement les erreurs et sera correctement testé.
Maintenant, nous allons découvrir quelques fonctionnalités de Rust qui ont été influencées par les langages fonctionnels : les fermetures et les itérateurs.