La différence entre sys.stdout.write et print?

376

Y a-t-il des situations dans lesquelles sys.stdout.write()est préférable print?

( Exemples: meilleures performances; code plus logique)

Johanna Larsson
la source
4
Quelle version de Python? 2.x ou 3.x?
Mark Byers
Honnêtement, j'aimerais savoir pour les deux, bien que je n'ai aucune expérience avec Python 3. Mise à jour de la question.
Johanna Larsson
17
@ S.Lott: demander les différences de base entre sys.stdout.write()et print(et / ou pourquoi Python a les deux) est une question parfaitement raisonnable et n'a pas besoin d'exemples. OP n'a pas dit que la syntaxe de la commande prêtait à confusion.
smci

Réponses:

294

printest juste un wrapper fin qui formate les entrées (modifiables, mais par défaut avec un espace entre args et newline à la fin) et appelle la fonction d'écriture d'un objet donné. Par défaut, cet objet est sys.stdout, mais vous pouvez passer un fichier en utilisant le formulaire "chevron". Par exemple:

print >> open('file.txt', 'w'), 'Hello', 'World', 2+3

Voir: https://docs.python.org/2/reference/simple_stmts.html?highlight=print#the-print-statement


En Python 3.x, printdevient une fonction, mais il est toujours possible de passer autre chose que sys.stdoutgrâce à l' fileargument.

print('Hello', 'World', 2+3, file=open('file.txt', 'w'))

Voir https://docs.python.org/3/library/functions.html#print


En Python 2.6+, printest toujours une instruction, mais elle peut être utilisée comme une fonction avec

from __future__ import print_function

Mise à jour: Bakuriu a commenté pour souligner qu'il existe une petite différence entre la fonction d'impression et l'instruction d'impression (et plus généralement entre une fonction et une instruction).

En cas d'erreur lors de l'évaluation des arguments:

print "something", 1/0, "other" #prints only something because 1/0 raise an Exception

print("something", 1/0, "other") #doesn't print anything. The function is not called
luc
la source
64
Il est également intéressant de noter que cela printajoute également une nouvelle ligne à tout ce que vous écrivez, ce qui ne se produit pas sys.stdout.write.
Michael Mior
5
Est également sys.stdout.writeplus universel si vous avez besoin d'écrire du code à double version (par exemple, du code qui fonctionne simultanément avec Python 2.x et Python 3.x).
andreb
3
@MichaelMior Vous pouvez supprimer la nouvelle ligne qui prints'ajoute avec une virgule de fin:print "this",; print "on the same line as this"
drevicko
1
@ bjd2385 Le >>n'est pas ici l'opérateur rshift mais une forme spécifique "chevron" de l' printinstruction. Voir docs.python.org/2/reference/…
luc
5
sys.stdout.write()tamponne également l'entrée et peut ne pas vider immédiatement l'entrée dans le fd. afin de vous assurer qu'il se comporte comme la fonction d'impression, vous devez ajouter: sys.stdout.flush()
kerbelp
151

printconvertit d'abord l'objet en chaîne (s'il ne s'agit pas déjà d'une chaîne). Il mettra également un espace avant l'objet s'il n'est pas le début d'une ligne et un caractère de nouvelle ligne à la fin.

Lors de l'utilisation stdout, vous devez convertir l'objet en chaîne vous-même (en appelant "str", par exemple) et il n'y a pas de caractère de nouvelle ligne.

Donc

print 99

est équivalent à:

import sys
sys.stdout.write(str(99) + '\n')
dogbane
la source
32
+1 pour avoir mentionné le caractère de nouvelle ligne! C'est la principale différence entre printet .write(), je dirais.
Eric O Lebigot
9
REMARQUE: printpeut être fait pour omettre la nouvelle ligne. Dans Python 2.x, mettez une virgule à la fin et un caractère espace sera affiché, mais pas de nouvelle ligne. Par exemple, print 99,en Python 3, vous print(..., end='')éviterez d'ajouter de la nouvelle ligne (et vous éviterez également d'ajouter de l'espace, sauf si vous le faites end=' '.
ToolmakerSteve
40
@EOL Comme c'est drôle, que quelqu'un nommé EOL fasse un commentaire sur '\ n' ... Ça m'a fait rire. Je n'ai pas de vie. Tue-moi.
Depado
2
ce n'est PAS vrai, l' printopération se comporte légèrement différemment dans les gestionnaires de signaux en python2.X, c'est-à-dire que l'impression ne peut pas être remplacée par sys.stdout dans l'exemple: stackoverflow.com/questions/10777610/…
ddzialak
41

Ma question est de savoir s'il existe ou non des situations dans lesquelles il sys.stdout.write()est préférable print

Après avoir fini de développer un script l'autre jour, je l'ai téléchargé sur un serveur Unix. Tous mes messages de débogage utilisaient des printinstructions, et celles - ci n'apparaissent pas dans un journal de serveur.

C'est un cas où vous pourriez avoir besoin à la sys.stdout.writeplace.

LiamSullivan
la source
8
hein? Êtes-vous sûr qu'il s'agit d'une différence entre print()et sys.stdout.write(), par opposition à la différence entre stdoutet stderr? Pour le débogage, vous devez utiliser le loggingmodule, qui imprime les messages dans stderr.
ostrokach
1
Ouais. Il en va de même pour l'utilisation nohupet la redirection vers un .outfichier.
conner.xyz
1
l'utilisation de sys.stdout.flush () serait utile.
suprit chaudhary
Si vous utilisez nohup, par défaut, toutes les écritures vers stdoutet stderrseront redirigées vers nohup.out, sans tenir compte de si vous utilisez printou stdout.write.
Zheng Liu
40

Voici un exemple de code basé sur le livre Learning Python de Mark Lutz qui répond à votre question:

import sys
temp = sys.stdout                 # store original stdout object for later
sys.stdout = open('log.txt', 'w') # redirect all prints to this log file
print("testing123")               # nothing appears at interactive prompt
print("another line")             # again nothing appears. it's written to log file instead
sys.stdout.close()                # ordinary file object
sys.stdout = temp                 # restore print commands to interactive prompt
print("back to normal")           # this shows up in the interactive prompt

L'ouverture de log.txt dans un éditeur de texte révélera ce qui suit:

testing123
another line
Will Townes
la source
Existe-t-il un moyen pour que je puisse imprimer à l'écran et écrire dans le fichier?
Devesh Saini
5
@DeveshSaini: Oui, il suffit d'écraser sys.stdout avec une classe proxy qui a au moins une fonction write () et flush (). J'ai écrit un exemple d'extrait ici .
ponycat
14

Il y a au moins une situation dans laquelle vous voulez sys.stdoutau lieu d'imprimer.

Lorsque vous souhaitez remplacer une ligne sans passer à la ligne suivante, par exemple lorsque vous dessinez une barre de progression ou un message d'état , vous devez parcourir en boucle quelque chose comme

Note carriage return-> "\rMy Status Message: %s" % progress

Et puisque l'impression ajoute une nouvelle ligne, il vaut mieux utiliser sys.stdout.

Carlos
la source
2
Si print ajoute une nouvelle ligne, pourquoi ne pas simplement imprimer ('message', end = '') à la place?
Apoorv Patne
8

Ma question est de savoir s'il existe ou non des situations dans lesquelles il sys.stdout.write()est préférableprint

Si vous écrivez une application en ligne de commande qui peut écrire à la fois dans des fichiers et dans stdout, c'est pratique. Vous pouvez faire des choses comme:

def myfunc(outfile=None):
    if outfile is None:
        out = sys.stdout
    else:
        out = open(outfile, 'w')
    try:
        # do some stuff
        out.write(mytext + '\n')
        # ...
    finally:
        if outfile is not None:
            out.close()

Cela signifie que vous ne pouvez pas utiliser le with open(outfile, 'w') as out:modèle, mais cela en vaut parfois la peine.

Hamish Downer
la source
À strictement parler, vous pouvez utiliser with- def process(output): # .../ if outfile is None: process(sys.stdout) else: with open(outfile, 'w') as out: process(out)(en ajoutant des sauts de ligne si nécessaire bien sûr). Ce n'est certainement pas très propre, c'est sûr.
Fund Monica's Lawsuit
4

Dans 2.x, l' printinstruction pré-traite ce que vous lui donnez, le transformant en chaînes en cours de route, gérant les séparateurs et les nouvelles lignes et permettant la redirection vers un fichier. 3.x le transforme en fonction, mais il a toujours les mêmes responsabilités.

sys.stdout est un fichier ou un fichier similaire qui a des méthodes d'écriture qui prennent des chaînes ou quelque chose le long de cette ligne.

Ignacio Vazquez-Abrams
la source
3

il est préférable lorsque l'impression dynamique est utile, par exemple, pour donner des informations dans un long processus:

import time, sys
Iterations = 555
for k in range(Iterations+1):
    # some code to execute here ...
    percentage = k / Iterations
    time_msg = "\rRunning Progress at {0:.2%} ".format(percentage)
    sys.stdout.write(time_msg)
    sys.stdout.flush()
    time.sleep(0.01)
Shivid
la source
2
print (time_msg, end = '') à la place sys.stdout.write (time_msg) sys.stdout.flush () fonctionne également
rluts
2
>>> sys.stdout.write(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: expected a string or other character buffer object
>>> sys.stdout.write("a")
a>>> sys.stdout.write("a") ; print(1)
a1

En observant l'exemple ci-dessus:

  1. sys.stdout.writene pas écrire objet non-chaîne, mais printsera

  2. sys.stdout.writene sera pas ajouter un nouveau symbole de ligne à la fin, mais printsera

Si nous plongeons profondément,

sys.stdout est un objet fichier qui peut être utilisé pour la sortie de print ()

si l'argument de fichier print()n'est pas spécifié, sys.stdoutsera utilisé

GraceMeng
la source
1

Existe-t-il des situations dans lesquelles sys.stdout.write () est préférable d'imprimer?

Par exemple, je travaille sur une petite fonction qui imprime des étoiles au format pyramide en passant le nombre comme argument, bien que vous puissiez accomplir cela en utilisant end = "" pour imprimer sur une ligne séparée, j'ai utilisé sys.stdout.write en coordination avec impression pour faire ce travail. Pour élaborer sur ce stdout.write imprime sur la même ligne où print imprime toujours son contenu sur une ligne distincte.

import sys

def printstars(count):

    if count >= 1:
        i = 1
        while (i <= count):
            x=0
            while(x<i):
                sys.stdout.write('*')
                x = x+1
            print('')
            i=i+1

printstars(5)
Sree
la source
1

Existe-t-il des situations dans lesquelles sys.stdout.write () est préférable d'imprimer?

J'ai trouvé que stdout fonctionne mieux que l'impression dans une situation multithreading. J'utilise Queue (FIFO) pour stocker les lignes à imprimer et je tiens tous les threads avant la ligne d'impression jusqu'à ce que mon Q d'impression soit vide. Même ainsi, en utilisant l'impression, je perds parfois le \ n final sur les E / S de débogage (en utilisant l'IDE pro pro).

Lorsque j'utilise std.out avec \ n dans la chaîne, les formats d'E / S de débogage sont correctement affichés et les \ n s'affichent avec précision.

David Poundall
la source
Connaissez-vous une raison pour laquelle la sortie standard devrait mieux fonctionner que l'impression dans ce cas, ou est-ce anecdotique? Pourriez-vous fournir un exemple de travail minimal où cela se produit?
user2653663
Je pense que stdout fonctionne à un niveau inférieur à celui de print. J'ai certainement eu une corruption de threads car deux routines d'impression se battaient pour passer par la sortie standard. L'écriture dans stdout one de chaque thread a supprimé la corruption pour moi.
David Poundall
stackoverflow.com/questions/7877850/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1

Dans Python 3, il existe une raison valable d'utiliser l'impression sys.stdout.write, mais cette raison peut également être transformée en une raison d'utiliser à la sys.stdout.writeplace.

Cette raison est que, maintenant, print est une fonction en Python 3, vous pouvez remplacer cela. Vous pouvez donc utiliser print partout dans un script simple et décider à la place de ces instructions print stderr. Vous pouvez maintenant simplement redéfinir la fonction d'impression, vous pouvez même changer la fonction d'impression globale en la modifiant à l'aide du module intégré. Bien sûr, file.writevous pouvez spécifier ce qu'est un fichier, mais avec l'écrasement de l'impression, vous pouvez également redéfinir le séparateur de lignes ou le séparateur d'arguments.

L'inverse est. Peut-être êtes-vous absolument certain d'écrire stdout, mais sachez également que vous allez changer l'impression en quelque chose d'autre, vous pouvez décider d'utilisersys.stdout.write et utiliser l'impression pour le journal des erreurs ou autre chose.

Donc, ce que vous utilisez dépend de la façon dont vous comptez l'utiliser. printest plus flexible, mais cela peut être une raison pour l'utiliser et pour ne pas l'utiliser. J'opterais toujours pour la flexibilité à la place et choisirais d'imprimer. Une autre raison d'utiliser à la printplace est la familiarité. Plus de gens comprendront maintenant ce que vous entendez par impression et moins savent sys.stdout.write.

Hielke Walinga
la source
1

L'une des différences est la suivante, lorsque vous essayez d'imprimer un octet dans son apparence hexadécimale. Par exemple, nous savons que la valeur décimale de 255est 0xFFen apparence hexadécimale:

val = '{:02x}'.format(255) 

sys.stdout.write(val) # prints ff2
print(val)            # prints ff
truthadjustr
la source
Ce n'est pas de cela qu'il s'agit. Cela ne se produirait que dans un shell interactif et parce que ... write()n'a pas ajouté \net retourne (et affiche le shell interactif) la valeur de retour de la fonction (nombre de caractères écrits), la représentation hexadécimale ou tout autre contenu affiché est sans importance.
Ondrej K.
0

En python 2, si vous devez passer une fonction, vous pouvez affecter os.sys.stdout.write à une variable, vous ne pouvez pas le faire (dans la repl) avec print.

>import os
>>> cmd=os.sys.stdout.write
>>> cmd('hello')
hello>>> 

Cela fonctionne comme prévu.

>>> cmd=print
  File "<stdin>", line 1
    cmd=print
            ^
SyntaxError: invalid syntax

Cela ne fonctionne pas. l'impression est une fonction magique.

shanecandoit
la source
0

Une différence entre printet sys.stdout.writeà signaler en Python 3, est également la valeur qui est retournée lorsqu'elle est exécutée dans le terminal. En Python 3 sys.stdout.writeretourne la longueur de la chaîne alors que printretourne justeNone .

Ainsi, par exemple, exécuter le code suivant de manière interactive dans le terminal afficherait la chaîne suivie de sa longueur, car la longueur est renvoyée et sortie lorsqu'elle est exécutée de manière interactive:

>>> sys.stdout.write(" hi ")
 hi 4
Armando Andres Flores
la source