Question Comment imprimer sur stderr dans Python 2?


J'ai trouvé au moins trois façons d'imprimer sur stderr:

 import sys

 print >> sys.stderr, 'spam'

 sys.stderr.write('spam\n')

 from __future__ import print_function
 print('spam', file=sys.stderr)

Cela semble contredire zen de Python # 13  , alors quelle est la meilleure façon de le faire? Y a-t-il des avantages ou des inconvénients d'une façon ou d'une autre?

  Il devrait y avoir un - et de préférence un seul - moyen évident de le faire.


988
2018-04-07 00:59


origine


Réponses:


J'ai trouvé ceci pour être le seul court + flexible + portable + lisible:

from __future__ import print_function
import sys

def eprint(*args, **kwargs):
    print(*args, file=sys.stderr, **kwargs)

La fonction eprint peut être utilisé de la même manière que la norme print fonction:

>>> print("Test")
Test
>>> eprint("Test")
Test
>>> eprint("foo", "bar", "baz", sep="---")
foo---bar---baz

845
2018-02-20 13:31



sys.stderr.write() est mon choix, juste plus lisible et en disant exactement ce que vous avez l'intention de faire et portable sur les versions.

Edit: être 'pythonic' est une troisième pensée pour moi sur la lisibilité et la performance ... avec ces deux choses à l'esprit, avec python 80% de votre code sera pythonique. la compréhension de la liste étant la «grande chose» qui n'est pas utilisée aussi souvent (lisibilité).


399
2018-04-07 01:03



Pour Python 2 mon choix est: print >> sys.stderr, 'spam' Parce que vous pouvez simplement imprimer des listes / dicts etc. sans le convertir en chaîne. print >> sys.stderr, {'spam': 'spam'} au lieu de: sys.stderr.write(str({'spam': 'spam'}))


120
2017-11-08 17:29



print >> sys.stderr est parti en Python3. http://docs.python.org/3.0/whatsnew/3.0.html dit:

Old: print >>sys.stderr, "fatal error"
New: print("fatal error", file=sys.stderr)

Malheureusement, c'est assez moche. Alternativement, utilisez

sys.stderr.write("fatal error\n")

mais notez que write n'est pas un remplacement 1: 1 pour print.


97
2018-04-04 10:00



Personne n'est mentionné logging encore, mais la journalisation a été créée spécifiquement pour communiquer des messages d'erreur. Par défaut, il est configuré pour écrire dans stderr. Ce script:

# foo.py
import logging
logging.basicConfig(format='%(message)s')

logging.warn('I print to stderr by default')
logging.info('For this you must change the level and add a handler.')
print('hello world')

a le résultat suivant lorsqu'il est exécuté sur la ligne de commande:

$ python3 foo.py > bar.txt
I print to stderr by default

(et bar.txt contient le 'hello world')


52
2017-12-23 16:04



Je dirais que votre première approche:

print >> sys.stderr, 'spam' 

est celui . . . évident façon de le faire "Les autres ne satisfont pas la règle # 1 (" Beautiful is better than laid. ")


32
2018-04-07 01:05



J'ai fait ce qui suit en utilisant Python 3:

from sys import stderr

def print_err(*args, **kwargs):
    print(*args, file=stderr, **kwargs)

Alors maintenant je suis capable d'ajouter des arguments de mots-clés, par exemple, pour éviter le retour chariot:

print_err("Error: end of the file reached. The word ", end='')
print_err(word, "was not found")

28
2017-12-29 21:40



Cela imitera la fonction d'impression standard mais sortira sur stderr

def print_err(*args):
    sys.stderr.write(' '.join(map(str,args)) + '\n')

18
2017-10-06 07:42



MODIFIER En arrière-plan, je pense que la confusion potentielle avec le changement de sys.stderr et ne voyant pas le comportement mis à jour rend cette réponse pas aussi bonne que d'utiliser une simple fonction comme d'autres l'ont souligné.

L'utilisation d'une partie seulement vous permet d'économiser 1 ligne de code. La confusion potentielle ne vaut pas la peine d'économiser 1 ligne de code.

original

Pour le rendre encore plus facile, voici une version qui utilise 'partial', ce qui est d'une grande aide dans les fonctions d'encapsulation.

from __future__ import print_function
import sys
from functools import partial

error = partial(print, file=sys.stderr)

Vous l'utilisez ensuite comme si

error('An error occured!')

Vous pouvez vérifier qu'il imprime sur stderr et non sur stdout en procédant comme suit (code de http://coreygoldberg.blogspot.com.au/2009/05/python-redirect-or-turn-off-stdout-and.html):

# over-ride stderr to prove that this function works.
class NullDevice():
    def write(self, s):
        pass
sys.stderr = NullDevice()

# we must import print error AFTER we've removed the null device because
# it has been assigned and will not be re-evaluated.
# assume error function is in print_error.py
from print_error import error

# no message should be printed
error("You won't see this error!")

L'inconvénient est partiel assigne la valeur de sys.stderr à la fonction enveloppée au moment de la création. Ce qui signifie, Si vous redirigez stderr plus tard, cela n'affectera pas cette fonction. Si vous envisagez de rediriger stderr, utilisez la méthode ** kwargs mentionnée par aaguirre sur cette page.


16
2017-12-30 02:13



La même chose s'applique à stdout:

print 'spam'
sys.stdout.write('spam\n')

Comme indiqué dans les autres réponses, impression offre une jolie interface qui est souvent plus pratique (par exemple pour imprimer des informations de débogage), écrire est plus rapide et peut également être plus pratique lorsque vous devez formater la sortie exactement d'une certaine manière. Je considérerais aussi la maintenabilité:

  1. Vous pouvez décider ultérieurement de basculer entre stdout / stderr et un fichier normal.

  2. impression() la syntaxe a changé dans Python 3, donc si vous avez besoin de supporter les deux versions, écrire() pourrait être mieux.


6
2017-11-01 11:58



Je travaille en python 3.4.3. Je coupe un peu de frappe qui montre comment je suis arrivé ici:

[18:19 jsilverman@JSILVERMAN-LT7 pexpect]$ python3
>>> import sys
>>> print("testing", file=sys.stderr)
testing
>>>
[18:19 jsilverman@JSILVERMAN-LT7 pexpect]$ 

Ça a marché? Essayez de rediriger stderr vers un fichier et voyez ce qui se passe:

[18:22 jsilverman@JSILVERMAN-LT7 pexpect]$ python3 2> /tmp/test.txt
>>> import sys
>>> print("testing", file=sys.stderr)
>>> [18:22 jsilverman@JSILVERMAN-LT7 pexpect]$
[18:22 jsilverman@JSILVERMAN-LT7 pexpect]$ cat /tmp/test.txt
Python 3.4.3 (default, May  5 2015, 17:58:45)
[GCC 4.9.2] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
testing

[18:22 jsilverman@JSILVERMAN-LT7 pexpect]$

Eh bien, mis à part le fait que la petite introduction que python vous donne a été envoyée dans stderr (où d'autre irait-elle?), Ça marche.


4
2018-02-10 02:29