¿La diferencia entre sys.stdout.write e print?

376

¿Hay situaciones en las que sys.stdout.write()es preferible print?

( Ejemplos: mejor rendimiento; código que tiene más sentido)

Johanna Larsson
fuente
44
¿Qué versión de Python? 2.xo 3.x?
Mark Byers
Sinceramente, me gustaría saber para ambos, aunque no tengo experiencia con Python 3. Actualicé la pregunta.
Johanna Larsson
17
@ S.Lott: preguntar las diferencias básicas entre sys.stdout.write()y print(y / o por qué Python tiene ambas) es una pregunta perfectamente razonable y no necesita ejemplos. OP no dijo que la sintaxis del comando era confusa.
smci

Respuestas:

294

printes solo un contenedor delgado que formatea las entradas (modificables, pero por defecto con un espacio entre args y nueva línea al final) y llama a la función de escritura de un objeto dado. Por defecto, este objeto es sys.stdout, pero puede pasar un archivo usando el formulario "chevron". Por ejemplo:

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

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


En Python 3.x, se printconvierte en una función, pero aún es posible pasar algo más que sys.stdoutgracias al fileargumento.

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

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


En Python 2.6+, printsigue siendo una declaración, pero se puede usar como una función con

from __future__ import print_function

Actualización: Bakuriu comentó para señalar que existe una pequeña diferencia entre la función de impresión y la declaración de impresión (y más generalmente entre una función y una declaración).

En caso de error al evaluar argumentos:

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
fuente
64
También vale la pena señalar que printtambién agrega una nueva línea a lo que escriba que no sucede sys.stdout.write.
Michael Mior
55
También sys.stdout.writees más universal si alguna vez necesita escribir código de versión dual (por ejemplo, código que funciona simultáneamente con Python 2.x y Python 3.x).
andreb
3
@MichaelMior Puede suprimir la nueva línea que se printagrega con una coma final:print "this",; print "on the same line as this"
drevicko
1
@ bjd2385 El >>no es el operador rshift aquí, sino una forma específica "chevron" de la printdeclaración. Ver docs.python.org/2/reference/…
luc
55
sys.stdout.write()también almacena la entrada en la memoria intermedia y es posible que no elimine la entrada al fd de inmediato. para asegurarse de que se comporta como la función de impresión, debe agregar: sys.stdout.flush()
kerbelp
151

printprimero convierte el objeto en una cadena (si aún no es una cadena). También pondrá un espacio antes del objeto si no es el comienzo de una línea y un carácter de nueva línea al final.

Cuando se usa stdout, debe convertir el objeto en una cadena usted mismo (llamando a "str", por ejemplo) y no hay un carácter de nueva línea.

Entonces

print 99

es equivalente a:

import sys
sys.stdout.write(str(99) + '\n')
dogbane
fuente
32
¡+1 por mencionar el personaje de nueva línea! Esta es la principal diferencia entre printy .write(), yo diría.
Eric O Lebigot
99
NOTA: printse puede hacer que omita la nueva línea. En Python 2.x, coloque una coma al final y se generará un carácter de espacio, pero no una nueva línea. Por ejemplo, print 99,en Python 3, print(..., end='')evitará agregar nueva línea (y también evitará agregar espacio, a menos que lo haga end=' '.)
ToolmakerSteve
40
@EOL Qué gracioso es que alguien llamado EOL haga un comentario sobre '\ n' ... Me hizo reír. No tengo vida. Mátame.
Depado
2
eso NO es cierto, la printoperación se comporta ligeramente diferente en los manejadores de señales en python2.X, es decir, la impresión no se puede reemplazar con sys.stdout, por ejemplo: stackoverflow.com/questions/10777610/…
ddzialak
41

Mi pregunta es si hay situaciones en las que sys.stdout.write()es preferible o no print

Después de terminar de desarrollar un script el otro día, lo cargué en un servidor Unix. Todos mis mensajes de depuración usaban printdeclaraciones, y estas no aparecen en el registro del servidor.

Este es un caso en el que puede necesitar en su sys.stdout.writelugar.

LiamSullivan
fuente
8
eh? ¿Estás seguro de que esta es una diferencia entre print()y sys.stdout.write(), a diferencia de la diferencia entre stdouty stderr? Para la depuración, debe usar el loggingmódulo, que imprime los mensajes stderr.
ostrokach
1
Ya Lo mismo es cierto con el uso nohupy la redirección a un .outarchivo.
conner.xyz
1
El uso de sys.stdout.flush () ayudaría.
suprit chaudhary
Si usa nohup, por defecto, toda la escritura stdouty stderrserá redirigida a nohup.out, sin tener en cuenta si usa printo stdout.write.
Zheng Liu
40

Aquí hay un código de muestra basado en el libro Learning Python de Mark Lutz que aborda su pregunta:

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

Abrir log.txt en un editor de texto revelará lo siguiente:

testing123
another line
Will Townes
fuente
¿Hay alguna manera de que pueda imprimir en la pantalla y escribir en el archivo?
Devesh Saini
55
@DeveshSaini: Sí, simplemente sobrescriba sys.stdout con una clase proxy que tenga al menos una función write () y flush (). Escribí un fragmento de ejemplo aquí .
ponycat
14

Hay al menos una situación en la que desea en sys.stdoutlugar de imprimir.

Cuando desee sobrescribir una línea sin pasar a la siguiente línea, por ejemplo, al dibujar una barra de progreso o un mensaje de estado , debe recorrer algo como

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

Y dado que la impresión agrega una nueva línea, es mejor usarla sys.stdout.

Carlos
fuente
2
Si print agrega una nueva línea, ¿por qué no simplemente imprimir ('message', end = '') en su lugar?
Apoorv Patne
8

Mi pregunta es si hay situaciones en las que sys.stdout.write()es preferible o noprint

Si está escribiendo una aplicación de línea de comandos que puede escribir tanto en archivos como en stdout, entonces es útil. Puedes hacer cosas como:

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

Significa que no puede usar el with open(outfile, 'w') as out:patrón, pero a veces vale la pena.

Hamish Downer
fuente
Estrictamente hablando, puede usar with- def process(output): # .../ if outfile is None: process(sys.stdout) else: with open(outfile, 'w') as out: process(out)(agregar nuevas líneas cuando sea necesario, por supuesto). Sin embargo, definitivamente no está muy limpio, eso es seguro.
Financia la demanda de Mónica el
4

En 2.x, la printdeclaración procesa previamente lo que le da, convirtiéndolo en cadenas en el camino, manejando separadores y nuevas líneas, y permitiendo la redirección a un archivo. 3.x lo convierte en una función, pero aún tiene las mismas responsabilidades.

sys.stdout es un archivo similar a un archivo que tiene métodos para escribir que toman cadenas o algo por el estilo.

Ignacio Vazquez-Abrams
fuente
3

Es preferible cuando la impresión dinámica es útil, por ejemplo, para proporcionar información en un proceso largo:

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
fuente
2
print (time_msg, end = '') en su lugar sys.stdout.write (time_msg) sys.stdout.flush () también funciona
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

Observando el ejemplo anterior:

  1. sys.stdout.writeno escribirá objetos que no sean cadenas, pero lo printhará

  2. sys.stdout.writeno agregará un nuevo símbolo de línea al final, pero lo printhará

Si nos sumergimos profundamente,

sys.stdout es un objeto de archivo que se puede usar para la salida de print ()

si print()no se especifica el argumento de archivo , sys.stdoutse utilizará

GraceMeng
fuente
1

¿Hay situaciones en las que es preferible imprimir sys.stdout.write ()?

Por ejemplo, estoy trabajando en una función pequeña que imprime estrellas en formato piramidal al pasar el número como argumento, aunque puede lograr esto usando end = "" para imprimir en una línea separada, usé sys.stdout.write en coordinación con estampado para que esto funcione. Para elaborar sobre este stdout.write imprime en la misma línea donde como print siempre imprime su contenido en una línea separada.

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
fuente
1

¿Hay situaciones en las que es preferible imprimir sys.stdout.write ()?

He descubierto que stdout funciona mejor que imprimir en una situación de subprocesos múltiples. Uso Queue (FIFO) para almacenar las líneas para imprimir y mantengo todos los hilos antes de la línea de impresión hasta que mi Q de impresión esté vacía. Aun así, usando la impresión, a veces pierdo el \ n final en la E / S de depuración (usando wing pro IDE).

Cuando uso std.out con \ n en la cadena, la E / S de depuración se formatea correctamente y los \ n se muestran con precisión.

David Poundall
fuente
¿Conoces alguna razón por la cual stdout debería funcionar mejor que la impresión en este caso, o es anecdótico? ¿Podría proporcionar un ejemplo de trabajo mínimo donde esto sucede?
user2653663
Mi opinión es que stdout funciona a un nivel más bajo que la impresión. Definitivamente tuve corrupción de hilo ya que dos rutinas de impresión estaban luchando para alimentarse a través de stdout. Escribir en stdout uno de cada hilo eliminó la corrupción para mí.
David Poundall
stackoverflow.com/questions/7877850/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1

En Python 3 hay una razón válida para usar print over sys.stdout.write, pero esta razón también se puede convertir en una razón para usar sys.stdout.writeen su lugar.

Esta razón es que, ahora imprimir es una función en Python 3, puede anular esto. Por lo tanto, puede usar imprimir en todas partes en un script simple y decidir en qué declaraciones de impresión deben escribir en su stderrlugar. Ahora puede redefinir la función de impresión, incluso podría cambiar la función de impresión global cambiándola usando el módulo integrado. Por supuesto confile.write , puede especificar qué archivo es, pero al sobrescribir la impresión también puede redefinir el separador de línea o separador de argumentos.

Al revés es. Tal vez esté absolutamente seguro de escribir stdout, pero también sabe que va a cambiar la impresión a otra cosa, puede decidir usarsys.stdout.write y usar la impresión para el registro de errores u otra cosa.

Entonces, lo que usa depende de cómo pretenda usarlo. printes más flexible, pero esa puede ser una razón para usarlo y no usarlo. Todavía optaría por la flexibilidad, y elegiría imprimir. Otra razón para usar printes la familiaridad. Ahora más personas entenderán lo que quiere decir con letra impresa y menos lo sabrán sys.stdout.write.

Hielke Walinga
fuente
1

Una de las diferencias es la siguiente, cuando se intenta imprimir un byte en su apariencia hexadecimal. Por ejemplo, sabemos que el valor decimal de 255está 0xFFen apariencia hexadecimal:

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

sys.stdout.write(val) # prints ff2
print(val)            # prints ff
truthadjustr
fuente
De eso no se trata. Solo sucedería en un shell interactivo y porque ... write()no agregó \ny devuelve (y muestra el shell interactivo) el valor de retorno de la función (número de caracteres escritos), la representación hexadecimal o cualquier otro contenido que se muestra es irrelevante.
Ondrej K.
0

En python 2, si necesita pasar una función, puede asignar os.sys.stdout.write a una variable, no puede hacer esto (en la respuesta) con print.

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

Eso funciona como se esperaba.

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

Eso no funciona. La impresión es una función mágica.

shanecandoit
fuente
0

Una diferencia entre printy sys.stdout.writepara señalar en Python 3, también es el valor que se devuelve cuando se ejecuta en la terminal. En Python 3 sys.stdout.writedevuelve la longitud de la cadena mientras que printsolo devuelve None.

Entonces, por ejemplo, ejecutar el siguiente código de forma interactiva en el terminal imprimiría la cadena seguida de su longitud, ya que la longitud se devuelve y se supera cuando se ejecuta de forma interactiva:

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