Hoe afdrukken naar Stderr in Python?

Er zijn verschillende manieren om naar Stderr te schrijven:

# Note: this first one does not work in Python 3
print >> sys.stderr, "spam"
sys.stderr.write("spam\n")
os.write(2, b"spam\n")
from __future__ import print_function
print("spam", file=sys.stderr)

Dat lijkt in tegenspraak te zijn met Zen van Python # 13 , dus wat is het verschil hier en zijn er voordelen of nadelen op de een of andere manier? Welke kant moet worden gebruikt?

Er moet één – en bij voorkeur slechts een voor de hand liggende manier zijn om het te doen.


Antwoord 1, Autoriteit 100%

Ik vond dit als het enige kort, flexibel, draagbaar en leesbaar:

from __future__ import print_function
import sys
def eprint(*args, **kwargs):
    print(*args, file=sys.stderr, **kwargs)

De functie eprintkan op dezelfde manier worden gebruikt als de standaard printfunctie:

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

Antwoord 2, Autoriteit 46%

import sys
sys.stderr.write()

is mijn keuze, gewoon meer leesbaar en zeggen precies wat u wilt doen en draagbaar over versies.

Bewerken: ‘Pythonic’ is een derde gedachte voor me over leesbaarheid en prestaties … met deze twee dingen in gedachten, met Python 80% van je code zal Pythonic zijn. Lijst begrijpen het ‘Big Thing’ dat niet zo vaak wordt gebruikt (leesbaarheid).


Antwoord 3, Autoriteit 19%

Python 2:

print >> sys.stderr, "fatal error"

Python 3:

print("fatal error", file=sys.stderr)

Lang antwoord

print >> sys.stderris verdwenen in Python3.
http://docs.python.org/3.0/whatsnew/3.0.htmlzegt:

Oud: print >> sys.stderr, "fatal error"
Nieuw: print("fatal error", file=sys.stderr)

Voor velen van ons voelt het wat onnatuurlijk om de bestemming naar het einde van de opdracht te verwijzen. Het alternatief

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

ziet er meer objectgericht uit en gaat elegant van het generieke naar het specifieke. Maar merk op dat writegeen 1:1 vervanging is voor print.


Antwoord 4, autoriteit 12%

Niemand heeft nog melding gemaakt van logging, maar logging is speciaal gemaakt om foutmeldingen te communiceren. De basisconfiguratie stelt een stream-handler in die naar stderr schrijft.

Dit script:

# foo.py
import logging
logging.basicConfig(format='%(message)s')
log = logging.getLogger(__name__)
log.warning('I print to stderr by default')
print('hello world')

heeft het volgende resultaat wanneer uitgevoerd op de opdrachtregel:

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

en bar.txt bevat de ‘Hallo World’ afgedrukt op stdout.


Antwoord 5, Autoriteit 10%

Voor Python 2 My Choice is:
print >> sys.stderr, 'spam'
Omdat u eenvoudig lijsten / dictten enz. Afdrukt, zult u deze in een string converteren.
print >> sys.stderr, {'spam': 'spam'}
in plaats van:
sys.stderr.write(str({'spam': 'spam'}))


Antwoord 6, Autoriteit 3%

Ik zou zeggen dat uw eerste aanpak:

print >> sys.stderr, 'spam' 

is de “One.. Duidelijk manier om het te doen” De anderen voldoen niet aan regel # 1 (“Mooi is beter dan lelijk.”)

– bewerken voor 2020 –

hierboven was mijn antwoord voor Python 2.7 in 2011. Nu dat Python 3 de standaard is, denk ik dat het antwoord “Rechts” is:

print("spam", file=sys.stderr) 

Antwoord 7, Autoriteit 3%

Ik heb het volgende gedaan met Python 3:

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

Dus nu kan ik bijvoorbeeld trefwoordargumenten toevoegen, bijvoorbeeld om koetsers terug te voorkomen:

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

Antwoord 8, Autoriteit 2%

In Python 3 kan men gewoon gebruiken print ():

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

bijna uit de doos:

import sys
print("Hello, world!", file=sys.stderr)

of:

from sys import stderr
print("Hello, world!", file=stderr)

Dit is eenvoudig en hoeft niets anders te bevatten dan sys.stderr.


Antwoord 9, autoriteit 2%

Dit bootst de standaard afdrukfunctie na, maar wordt uitgevoerd op stderr

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

Antwoord 10

BEWERKENAchteraf denk ik dat de mogelijke verwarring met het wijzigen van sys.stderr en het niet zien van het bijgewerkte gedrag dit antwoord niet zo goed maakt als het gebruik van een eenvoudige functie zoals anderen hebben opgemerkt.

Als u slechts gedeeltelijk gebruikt, bespaart u 1 regel code. De mogelijke verwarring is het niet waard om 1 regel code te bewaren.

origineel

Om het nog gemakkelijker te maken, is hier een versie die ‘gedeeltelijk’ gebruikt, wat een grote hulp is bij het inpakken van functies.

from __future__ import print_function
import sys
from functools import partial
error = partial(print, file=sys.stderr)

Je gebruikt het dan zo

error('An error occured!')

Je kunt controleren of het naar stderr en niet naar stdout wordt afgedrukt door het volgende te doen (code overschrijven van 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!")

Het nadeel hiervan is gedeeltelijk wijst de waarde van Sys.Stderr toe aan de gewikkelde functie op het moment van de schepping. Wat betekent, als u zich later doormaakt, heeft dit geen invloed op deze functie.
Als u van plan bent om Stderr door te sturen, gebruikt u de ** KWARGS-methode die wordt genoemd door AAGUIRRE op deze pagina.


Antwoord 11

Hetzelfde geldt voor stdout:

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

Zoals vermeld in de andere antwoorden, Print biedt een mooie interface die vaak handiger is (bijv. Voor het afdrukken van debug-informatie), terwijl schrijven sneller is en ook is Handiger wanneer u de uitvoer precies op een bepaalde manier moet formatteren. Ik zou ook rekening houden met het onderhoudbaarheid:

  1. U kunt later besluiten om te schakelen tussen StDout / Stderr en een regelmatig bestand.

  2. Afdrukken () Syntaxis is gewijzigd in Python 3, dus als u beide versies moet ondersteunen, is WRITE () beter.


Antwoord 12

Ik werk in Python 3.4.3. Ik ben een beetje typen uit dat laat zien hoe ik hier aankwam:

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

Is het gelukt? Probeer stderr om te leiden naar een bestand en kijk wat er gebeurt:

[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]$

Nou, afgezien van het feit dat de kleine introductie die python je geeft in stderr is geslurpt (waar zou het anders heen gaan?), werkt het.


Antwoord 13

Als je een programma wilt afsluiten vanwege een fatale fout, gebruik dan:

sys.exit("Your program caused a fatal error. ... description ...")

en import sysin de koptekst.


Antwoord 14

Als je een eenvoudige test doet:

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

Je zult merken dat sys.stderr.write() consequent 1.81keer sneller is!


Antwoord 15

Het antwoord op de vraag is: er zijn verschillende manieren om stderr in python af te drukken, maar dat hangt af van
1.) welke python-versie we gebruiken
2.) welke exacte output we willen.

Het verschil tussen de schrijffunctie van print en stderr:
stderr: stderr (standaardfout) is een pijp die in elk UNIX/Linux-systeem is ingebouwd. Wanneer je programma crasht en foutopsporingsinformatie afdrukt (zoals een traceback in Python), gaat het naar de stderr-pijp.

print: print is een wrapper die de invoer opmaakt (de invoer is de spatie tussen argument en de nieuwe regel aan het einde) en roept vervolgens de schrijffunctie van een bepaald object, het gegeven object op standaard is sys.stdout, maar we kunnen een bestand doorgeven, dwz we kunnen de invoer ook in een bestand afdrukken.

Python2:
Als we python2 gebruiken, dan

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

Python2 volgkomma is in Python3 een parameter geworden, dus als we gebruiken
volgkomma’s om de nieuwe regel na een afdruk te vermijden, dit zal in
Python3 ziet eruit als print(‘Text to print’, end=’ ‘) wat een syntaxis is
fout onder Python2.

http://python3porting.com/noconv.html

Als we hetzelfde hierboven scario in Python3 controleren3:

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

Under Python 2.6 Er is een toekomst importeren om af te drukken in een
functie. Dus om syntaxisfouten en andere verschillen en andere verschillen te vermijden
Moet elk bestand starten waar we afdrukken () gebruiken met Future Import
print_functie. De Future importeren werkt alleen onder Python 2.6 en
Later, dus voor Python 2.5 en eerder heb je twee opties. Jij kan
Converteer ofwel de complexere afdruk naar iets eenvoudiger, of dat kan
Gebruik een afzonderlijke afdrukfunctie die werkt onder zowel Python2 als
Python3.

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

Hoes: punt om op te merken dat Sys.Stderr.Write () of Sys.stdout.Write ()
(Stdout (standaarduitgang) is een pijp die is ingebouwd in elk
Unix / Linux-systeem) is geen vervanging voor afdrukken, maar ja we kunnen gebruiken
het als alternatief in een bepaald geval. Print is een wrapper die de
invoer met ruimte en newline aan het einde en gebruikt de schrijffunctie naar
schrijven. Dit is de reden van Sys.Stderr.Write () is sneller.

Opmerking: We kunnen ook traceren en debugg gebruiken met behulp van logboek

#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

Other episodes