web-dev-qa-db-fra.com

En quoi STDERR.puts est-il différent des puts en Ruby?

J'apprends le langage de la programmation Ruby 1.9, et ils jettent STDERR.puts dans un bloc de code au début du livre sans expliquer pourquoi ils l'utilisent ou en quoi il diffère des puts.

J'ai googlé et wikied le terme, mais tout ce que je peux rassembler de ma recherche est qu'il est impliqué dans les diagnostics. Nulle part dans le code fourni par Programming Ruby ne semble-t-il y avoir un lien vers la gestion des exceptions d'erreur.

Voici le code.

require_relative 'csv_reader'
reader = CsvReader.new
ARGV.each do |csv_file_name|
  STDERR.puts "Processing #{csv_file_name}"
  reader.read_in_csv_data(csv_file_name)
end

J'ai réussi à lire quelque part que STDERR.puts est utilisé pour la gestion des erreurs hors convention, mais je suppose que je demande si cela agit différemment de put.

39
rubynewbie

Par défaut, puts écrit dans STDOUT. En spécifiant STDERR.puts, vous envoyez votre sortie à la poignée STDERR. Bien que le comportement d'implémentation soit le même, l'utilisation de STDERR au lieu de STDOUT aura certainement un impact sur les consommateurs de votre programme, car ils tenteront de capturer la sortie de votre programme à partir de STDOUT, par convention. La meilleure pratique consiste à consigner les informations de débogage, les erreurs, les avertissements, l'état, etc. sur STDERR et la sortie réelle du programme sur STDOUT.

68
Palpatim

Dans un système basé sur * nix, lorsqu'un nouveau processus est démarré, il aura par défaut trois descripteurs de fichiers ouverts, comme suit

 0 - STDIN 
 1 - STDOUT 
 2 - STDERR 

Ces nombres, appelons-les, les descripteurs de fichiers sont importants pour le shell Unix que vous utilisez pour démarrer votre programme. STDIN est l'endroit où votre programme s'attend à obtenir son entrée (généralement le clavier, sauf si vous l'avez modifié). STDOUT est l'endroit où votre programme écrira sa sortie (généralement l'écran, sauf si vous l'avez modifié) et STDERR, où il écrira ses erreurs (toujours l'écran, à moins que vous ne l'ayez modifié).

La déclaration commune ci-dessus est "à moins que vous ne l'ayez modifiée". Si vous exécutez une commande comme celle-ci

command > file.out

Ensuite, la sortie (tout ce qui est écrit dans STDOUT) n'apparaîtra pas à l'écran, elle apparaîtra dans file.out. Si vous exécutez votre commande comme ceci

command 2> file.err

Ensuite, votre sortie réapparaîtra à l'écran mais toutes les erreurs écrites dans STDERR apparaîtront dans file.err. En réalité command > file.out est vraiment un raccourci pour command 1>file.out. Tout ce qui s'applique au symbole> (Redirection) s'applique également au | symbole pour la tuyauterie. Cela signifie que si vous exécutez votre programme en tant que filtre, en recevant des données sur STDIN et en écrivant sur STDOUT, les autres programmes peuvent recevoir leurs données de votre programme mais ils ne recevront pas les données écrites sur STDERR. (À moins que vous ne l'ayez demandé)

Vous pouvez utiliser ces deux commandes ensemble comme ceci.

command 1> file.out 2> file.err  # Generally you would leave out the 1

Dans ce cas, il n'est pas surprenant que la sortie et l'erreur se trouvent dans 2 fichiers distincts. Bash a également la notion de duplication des descripteurs de fichiers. Cela se fait avec> & operator. La commande suivante mettra STDOUT et STDERR dans le même fichier.

command > file.out 2>&1

Ce que cette commande dit est d'exécuter la commande configurant STDOUT pour être redirigé vers file.out puis dupliquer (> &) le descripteur de fichier 2 (STDERR) pour aller partout où le descripteur de fichier 1 va (file.out)

Vous devez être un peu prudent ici avec l'ordre dans lequel vous utilisez ces arguments. Comparez ce qui précède avec cette commande.

command 2>&1 > file.out

Cela a un résultat entièrement différent. Cette commande dit d'exécuter la commande et de dupliquer STDERR sur STDOUT (à ce stade du terminal), puis de rediriger STDOUT vers file.out. Votre texte d'erreur restera à l'écran.

24
Steve Weet

Chaque programme démarre avec trois descripteurs de fichiers standard lorsqu'ils sont générés: flux d'entrée, de sortie et d'erreur standard.

Le flux d'entrée standard est un flux générique à partir duquel l'entrée de programme doit être lue. De même, le flux de sortie standard est un flux générique dans lequel la sortie du programme peut être écrite. Alors, quelle est l'erreur standard?

La différence entre la sortie standard et l'erreur standard est subtile mais extrêmement importante dans les systèmes UNIX en raison de la façon dont les programmes sont utilisés ensemble via des canaux. Les programmes sont souvent conçus pour consommer la sortie d'autres programmes comme entrée; cela se fait en redirigeant la sortie standard d'un programme vers l'entrée standard d'un autre, souvent via l'opérateur pipe (|). Cela laisse l'erreur standard toujours connectée au terminal. L'utilisateur peut choisir d'afficher les données envoyées à ce flux dans le terminal lui-même, ou les rediriger vers un fichier journal, ou vers /dev/null, tout ce que l'utilisateur désire. Notez que les données envoyées à stderr ne doivent pas nécessairement être des messages d'erreur; ce ne sont que des données distinctes de la sortie réelle du programme.

La prise en charge de ce paradigme est extrêmement importante pour l'utilisabilité des programmes, car elle fournit une interface utilisateur prévisible vers l'entrée, la sortie et les messages du programme. L'utilisateur peut les manipuler comme bon lui semble et des applications souvent intéressantes surgissent de manière imprévue.

Ainsi, d'une manière générale, la sortie standard correspond à la sortie réelle et l'erreur standard à la communication avec l'utilisateur.

4
Matheus Moreira