write - Comment imprimer sur stderr en Python?




sys stderr write (10)

La réponse à la question est la suivante: Il existe différentes façons d'imprimer stderr en python mais cela dépend de 1.) quelle version de Python nous utilisons 2.) quelle sortie exacte nous voulons.

La différence entre print et la fonction d'écriture de stderr : stderr : stderr (erreur standard) est un pipe intégré à chaque système UNIX / Linux, lorsque votre programme plante et imprime des informations de débogage (comme une traceback en Python), il va à la stderr tuyau.

print : print est un wrapper qui formate les entrées (l'entrée est l'espace entre l'argument et le newline à la fin) et il appelle ensuite la fonction write d'un objet donné, l'objet donné par défaut est sys.stdout, mais nous pouvons passer un fichier à savoir nous pouvons imprimer l'entrée dans un fichier aussi.

Python2: Si nous utilisons python2 alors

>>> import sys
>>> print "hi"
hi
>>> print("hi")
hi
>>> print >> sys.stderr.write("hi")
hi

La virgule Python2 dans Python3 devient un paramètre, donc si nous utilisons des virgules pour éviter la nouvelle ligne après une impression, Python3 ressemblera à print ('Text to print', fin = '') qui est une erreur de syntaxe sous Python2 .

http://python3porting.com/noconv.html

Si nous vérifions même ci-dessus sceario dans python3:

>>> import sys
>>> print("hi")
hi

Sous Python 2.6 il y a une future importation pour faire imprimer dans une fonction. Donc, pour éviter les erreurs de syntaxe et d'autres différences, nous devrions commencer n'importe quel fichier où nous utilisons print () avec l'importation future fonction print_function. L'importation future ne fonctionne que sous Python 2.6 et versions ultérieures, donc pour Python 2.5 et versions antérieures, vous avez deux options. Vous pouvez convertir l'impression plus complexe en quelque chose de plus simple, ou vous pouvez utiliser une fonction d'impression distincte qui fonctionne sous Python2 et Python3.

>>> from __future__ import print_function
>>> 
>>> def printex(*args, **kwargs):
...     print(*args, file=sys.stderr, **kwargs)
... 
>>> printex("hii")
hii
>>>

Cas: À noter que sys.stderr.write () ou sys.stdout.write () (stdout (sortie standard) est un tube intégré à chaque système UNIX / Linux) ne remplace pas l'impression, mais oui nous pouvons l'utiliser comme une alternative dans certains cas. L'impression est un wrapper qui enveloppe l'entrée avec de l'espace et newline à la fin et utilise la fonction write pour écrire. C'est la raison pour laquelle sys.stderr.write () est plus rapide.

Remarque: nous pouvons également tracer et déboguer à l'aide de la journalisation

#test.py
import logging
logging.info('This is the existing protocol.')
FORMAT = "%(asctime)-15s %(clientip)s %(user)-8s %(message)s"
logging.basicConfig(format=FORMAT)
d = {'clientip': '192.168.0.1', 'user': 'fbloggs'}
logging.warning("Protocol problem: %s", "connection reset", extra=d)

https://docs.python.org/2/library/logging.html#logger-objects

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 moyen - et de préférence un seul - de le faire.


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

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

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")

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ée de la même manière que la fonction d' print standard:

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

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

[18:19 [email protected] pexpect]$ python3
>>> import sys
>>> print("testing", file=sys.stderr)
testing
>>>
[18:19 [email protected] pexpect]$ 

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

[18:22 [email protected] pexpect]$ python3 2> /tmp/test.txt
>>> import sys
>>> print("testing", file=sys.stderr)
>>> [18:22 [email protected] pexpect]$
[18:22 [email protected] 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 [email protected] 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.


La même chose s'applique à stdout:

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

Comme indiqué dans les autres réponses, print offre une jolie interface souvent plus pratique (par exemple pour imprimer des informations de débogage), tandis que write est plus rapide et peut être plus pratique lorsque vous devez formater la sortie de manière précise. Je considérerais aussi la maintenabilité:

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

  2. La syntaxe print () a changé dans Python 3, donc si vous avez besoin de supporter les deux versions, write () pourrait être meilleur.


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'}))


Si vous faites un test simple:

import time
import sys

def run1(runs):
    x = 0
    cur = time.time()
    while x < runs:
        x += 1
        print >> sys.stderr, 'X'
    elapsed = (time.time()-cur)
    return elapsed

def run2(runs):
    x = 0
    cur = time.time()
    while x < runs:
        x += 1
        sys.stderr.write('X\n')
        sys.stderr.flush()
    elapsed = (time.time()-cur)
    return elapsed

def compare(runs):
    sum1, sum2 = 0, 0
    x = 0
    while x < runs:
        x += 1
        sum1 += run1(runs)
        sum2 += run2(runs)
    return sum1, sum2

if __name__ == '__main__':
    s1, s2 = compare(1000)
    print "Using (print >> sys.stderr, 'X'): %s" %(s1)
    print "Using (sys.stderr.write('X'),sys.stderr.flush()):%s" %(s2)
    print "Ratio: %f" %(float(s1) / float(s2))

Vous trouverez que sys.stderr.write () est toujours 1.81 fois plus rapide!


sys.stderr.write() est mon choix, juste plus lisible et en disant exactement ce que vous avez l'intention de faire et portable entre 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é).


EDIT En rétrospective, 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 est en train d'imprimer 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 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 que la valeur de sys.stderr est affectée à la fonction enveloppée au moment de la création. Ce qui signifie que si vous redirigez stderr plus tard, cela n'affectera pas cette fonction. Si vous prévoyez de rediriger stderr, utilisez la méthode ** kwargs mentionnée par aaguirre sur cette page.





zen