You are here: Sommaire > Plongez au coeur de Python > Des scripts et des flots de données (streams) > Entrée, sortie et erreur standard | << >> | ||||
Plongez au coeur de PythonDe débutant à expert |
Les utilisateurs d'UNIX sont déjà familiers avec les concepts d'entrée standard, de sortie standard et d'erreur standard. Cette section s'adresse aux autres.
La sortie standard et l'erreur standard (communément abrégé en stdout et en stderr) sont des canaux de communication (pipes) intégrés à chaque système UNIX. Lorsque vous affichez (fonction print) quelque chose, il est dirigé vers le canal de communication stdout; quand votre programme plante et affiche des informations de débogage (comme un traceback en Python), elles sont envoyées vers le canal de communication stderr. Chacun de ces deux canaux sont d'ordinaire simplement connectés à la fenêtre du terminal avec laquelle vous travaillez et de cette façon vous voyez s'afficher la sortie du programme ou l'information de débogage s'il plante. (Si vous travaillez sur un système pourvu d'un IDE Python fenêtré, stdout et stderr sont redirigés par défaut vers la «Fenêtre Interactive».)
>>> for i in range(3): ... print 'Dive in' Dive in Dive in Dive in >>> import sys >>> for i in range(3): ... sys.stdout.write('Dive in') Dive inDive inDive in >>> for i in range(3): ... sys.stderr.write('Dive in') Dive inDive inDive in
Comme vous l'avez vu dans l'Exemple 6.9, «Compteurs simples», vous pouvez utiliser la fonction prédéfinie de Python range pour construire un simple compteur de boucles qui répète une instruction un nombre déterminé de fois. | |
stdout est un pseudo objet-fichier; appeler sa fonction write affichera toutes les chaînes que vous lui donnez. En fait, c'est bien ce que fait la fonction print; elle ajoute un retour chariot à la fin de la chaîne que vous affichez et appelle sys.stdout.write. | |
Dans le cas le plus simple, stdout et stderr envoient leur sortie au même endroit : l'IDE Python (si vous en utilisez un), ou la console (si vous avez lancé Python à partir de la ligne de commande). Comme stdout, stderr n'ajoute pas de retour chariot pour vous; si vous en avez besoin, ajoutez-les vous-même. |
stdout et stderr sont toutes les deux des pseudo objet-fichiers, comme ceux dont il a été question dans la Section 10.1, «Extraire les sources de données en entrée», mais ils sont tous les deux en écriture seule. Ils n'ont pas de méthode read, seulement une méthode write. Ils n'en restent pas moins des pseudo objet-fichiers auxquels vous pouvez assigner n'importe quel autre fichier - ou pseudo objet-fichier afin d'en rediriger la sortie.
[you@localhost kgp]$ python stdout.py Dive in [you@localhost kgp]$ cat out.log This message will be logged instead of displayed
(Avec Windows, il faut utiliser type au lieu de cat pour afficher le contenu d'un fichier.)
Si vous ne l’avez pas déjà fait, vous pouvez télécharger cet exemple ainsi que les autres exemples du livre.
#stdout.py import sys print 'Dive in' saveout = sys.stdout fsock = open('out.log', 'w') sys.stdout = fsock print 'This message will be logged instead of displayed' sys.stdout = saveout fsock.close()
Rediriger stderr fonctionne exactement de la même manière, en utilisant sys.stderr au lieu de sys.stdout.
[you@localhost kgp]$ python stderr.py [you@localhost kgp]$ cat error.log Traceback (most recent line last): File "stderr.py", line 5, in ? raise Exception, 'this error will be logged' Exception: this error will be logged
Si vous ne l’avez pas déjà fait, vous pouvez télécharger cet exemple ainsi que les autres exemples du livre.
#stderr.py import sys fsock = open('error.log', 'w') sys.stderr = fsock raise Exception, 'this error will be logged'
Puisqu'il est si trivial d'écrire des messages d'erreurs sur le canal d'erreur standard, il existe une syntaxe abrégée qui peut être utilisée plutôt que de s'embêter à effectuer une redirection complète.
>>> print 'entering function' entering function >>> import sys >>> print >> sys.stderr, 'entering function' entering function
L'entrée standard, de l'autre côté, est un objet-fichier en lecture seule et représente les données circulant entre un programme et un programme exécuté antérieurement. Cela n'a probablement pas grand sens pour les utilisateurs chevronnés de Mac OS, ou même pour les utilisateurs de Windows à moins que vous ne soyez coutumier de la ligne de commande MS-DOS. Son principe de fonctionnement vous permet de construire une chaîne de commandes sur une seule ligne, de telle sorte que la sortie d'un premier programme devienne l'entrée du programme suivant dans la chaîne. Le premier programme retourne simplement un résultat vers la sortie standard (sans effectuer lui-même une redirection spéciale, sinon le renvoi en sortie de quelques instructions print ou que sais-je encore), le programme suivant lit l'entrée standard, et le système d'exploitation se charge de connecter la sortie d'un programme à l'entrée du programme suivant.
[you@localhost kgp]$ python kgp.py -g binary.xml 01100111 [you@localhost kgp]$ cat binary.xml <?xml version="1.0"?> <!DOCTYPE grammar PUBLIC "-//diveintopython.org//DTD Kant Generator Pro v1.0//EN" "kgp.dtd"> <grammar> <ref id="bit"> <p>0</p> <p>1</p> </ref> <ref id="byte"> <p><xref id="bit"/><xref id="bit"/><xref id="bit"/><xref id="bit"/>\ <xref id="bit"/><xref id="bit"/><xref id="bit"/><xref id="bit"/></p> </ref> </grammar> [you@localhost kgp]$ cat binary.xml | python kgp.py -g - 10110001
Comme vous l'aviez vu dans la Section 9.1, «Plonger», cette commande affiche une chaîne de huit bits aléatoires, 0 ou 1. | |
Cette commande affiche simplement la totalité du contenu de binary.xml. (les utilisateurs de Windows doivent utiliser type au lieu de cat.) | |
Cette commande affiche le contenu de binary.xml, mais le caractère «|», appelé «pipe», signifie que le contenu ne sera pas affiché à l'écran. A la place, il deviendra l'entrée standard de la prochaine commande qui dans ce cas appelle votre script Python. | |
Plutôt que de spécifier un module (comme binary.xml), vous spécifiez «-», ce qui oblige votre script à charger la grammaire à partir de l'entrée standard au lieu d'un fichier particulier sur le disque. (Vous en saurez plus à ce propos dans le prochain exemple.) Ainsi le résultat est le même qu'avec la syntaxe précédente, où vous spécifiiez directement le nom du fichier de grammaire, mais pensez en plus aux nombreuses possibilités qui s'offrent à vous. Plutôt que de simplement exécuter cat binary.xml, vous pourriez lancer un premier script qui générerait dynamiquement une grammaire que vous redirigeriez vers votre script. Les données pourraient provenir de n'importe où : une base de données, un méta-script générateur de grammaire, ou que sais-je encore. L'important est que vous n'avez pas besoin de modifier votre script kgp.py pour tenir compte de cette fonctionnalité. Tout ce dont vous avez besoin, c'est de pouvoir récupérer le fichier de grammaire à partir de l'entrée standard et alors vous pouvez confier toute la logique restante à un autre programme. |
Comment donc notre script «sait»-il qu'il doit lire à partir de l'entrée standard quand le fichier de grammaire correspond à «-» ? Cela n'a rien de magique; juste logique.
def openAnything(source): if source == "-": import sys return sys.stdin # try to open with urllib (if source is http, ftp, or file URL) import urllib try: [... snip ...]
Il s'agit de la fonction openAnything de toolbox.py, que vous aviez précédemment examinée dans la Section 10.1, «Extraire les sources de données en entrée». Tout ce que vous avez fait est d'ajouter trois lignes de code au début de cette fonction pour tester si la source correspond à «-»; si c'est le cas, vous retournez sys.stdin. Rien de plus ! Souvenez-vous que stdin est un pseudo objet-fichier pourvu d'une méthode read, si bien que le reste du code (dans kgp.py où vous appelez openAnything) ne change pas d'un pouce. |
<< Des scripts et des flots de données (streams) |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
Mettre en cache la consultation de noeuds >> |