A diferença entre sys.stdout.write e print?

376

Existem situações em que sys.stdout.write()é preferível print?

( Exemplos: melhor desempenho; código que faz mais sentido)

Johanna Larsson
fonte
4
Qual versão do Python? 2.x ou 3.x?
Mark Byers
Honestamente, eu gostaria de saber para ambos, embora não tenha experiência com o Python 3. Atualizei a pergunta.
Johanna Larsson
17
@ S.Lott: pedir as diferenças básicas entre sys.stdout.write()e print(e / ou por que o Python possui os dois) é uma pergunta perfeitamente razoável e não precisa de exemplos. O OP não disse que a sintaxe do comando era confusa.
SMCI

Respostas:

294

printé apenas um invólucro fino que formata as entradas (modificáveis, mas por padrão com um espaço entre args e newline no final) e chama a função de gravação de um determinado objeto. Por padrão, esse objeto é sys.stdout, mas você pode transmitir um arquivo usando o formulário "chevron". Por exemplo:

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

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


No Python 3.x, printtorna-se uma função, mas ainda é possível passar algo diferente de sys.stdoutgraças ao fileargumento.

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

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


No Python 2.6+, printainda é uma instrução, mas pode ser usada como uma função com

from __future__ import print_function

Atualização: Bakuriu comentou ao ressaltar que há uma pequena diferença entre a função de impressão e a instrução de impressão (e, geralmente, entre uma função e uma instrução).

Em caso de erro ao avaliar 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
fonte
64
Também é importante notar que printtambém acrescenta uma nova linha ao que você escreve, o que não acontece sys.stdout.write.
Michael Mior
5
Também sys.stdout.writeé mais universal se você precisar escrever um código de versão dupla (por exemplo, código que funcione simultaneamente com o Python 2.x e o Python 3.x).
andreb
3
@MichaelMior Você pode suprimir a nova linha printanexada com uma vírgula à direita:print "this",; print "on the same line as this"
drevicko
11
@ bjd2385 Não >>é o operador rshift aqui, mas uma forma "chevron" específica da printdeclaração. Veja docs.python.org/2/reference/…
luc
5
sys.stdout.write()também armazena em buffer a entrada e pode não liberar a entrada para o fd imediatamente. a fim de se certificar de que ele se comporta como a função de impressão, você deve acrescentar: sys.stdout.flush()
kerbelp
151

printprimeiro converte o objeto em uma sequência (se ainda não for uma sequência). Ele também colocará um espaço antes do objeto, se não for o início de uma linha e um caractere de nova linha no final.

Ao usar stdout, você precisa converter o objeto em uma string (chamando "str", por exemplo) e não há caracteres de nova linha.

assim

print 99

é equivalente a:

import sys
sys.stdout.write(str(99) + '\n')
dogbane
fonte
32
+1 por mencionar o caractere de nova linha! Esta é a principal diferença entre printe .write(), eu diria.
Eric O Lebigot
9
NOTA: printpode ser feito para omitir a nova linha. No Python 2.x, coloque uma vírgula no final e um caractere de espaço será gerado, mas nenhuma nova linha. Por exemplo, print 99,em Python 3, print(..., end='')vai evitar a adição de nova linha (e também evitar a adição de espaço, a menos que você faça end=' '.
ToolmakerSteve
40
@EOL Que engraçado, que alguém chamado EOL faz um comentário sobre '\ n' ... Isso me fez rir. Eu não tenho vida. Me mata.
Depado 23/06
2
Isso não é verdade, printse comporta de operação ligeiramente diferentes em manipuladores de sinal em python2.x, ou seja, de impressão não pode ser substituído por sys.stdout no exemplo: stackoverflow.com/questions/10777610/...
ddzialak
41

Minha pergunta é se há ou não situações em que sys.stdout.write()é preferível print

Depois de terminar de desenvolver um script no outro dia, enviei-o para um servidor unix. Todas as minhas mensagens de depuração usavam printinstruções, e elas não aparecem no log do servidor.

Este é um caso em que você pode precisar sys.stdout.write.

LiamSullivan
fonte
8
Hã? Tem certeza de que essa é uma diferença entre print()e sys.stdout.write(), ao contrário da diferença entre stdoute stderr? Para depuração, você deve usar o loggingmódulo, que imprime mensagens para stderr.
ostrokach
11
Ya. O mesmo acontece com o uso nohupe o redirecionamento para um .outarquivo.
Conner.xyz
11
o uso de sys.stdout.flush () ajudaria.
suprit chaudhary
Se você usar nohup, por padrão, toda a escrita stdoute stderrserá redirecionada nohup.out, independentemente de você usar printou stdout.write.
Zheng Liu
40

Aqui está um exemplo de código baseado no livro Learning Python, de Mark Lutz, que aborda sua pergunta:

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 em um editor de texto revelará o seguinte:

testing123
another line
Will Townes
fonte
Existe alguma maneira de imprimir na tela e gravar no arquivo?
Devesh Saini
5
@DeveshSaini: Sim, basta substituir o sys.stdout por uma classe de proxy que tenha pelo menos uma função write () e flush (). Eu escrevi um exemplo de trecho aqui .
ponycat 21/05
14

Há pelo menos uma situação em que você deseja, em sys.stdoutvez de imprimir.

Quando você deseja sobrescrever uma linha sem passar para a próxima linha, por exemplo, ao desenhar uma barra de progresso ou uma mensagem de status , é necessário fazer um loop sobre algo como

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

E como a impressão adiciona uma nova linha, é melhor usá-lo sys.stdout.

Carlos
fonte
2
Se print adiciona uma nova linha, por que não apenas print ('message', end = '')?
Apoorv Patne 13/03
8

Minha pergunta é se há ou não situações em que sys.stdout.write()é preferívelprint

Se você estiver escrevendo um aplicativo de linha de comando que possa gravar nos arquivos e no stdout, será útil. Você pode fazer coisas 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()

Isso significa que você não pode usar o with open(outfile, 'w') as out:padrão, mas às vezes vale a pena.

Hamish Downer
fonte
A rigor, você pode usar with- def process(output): # .../ if outfile is None: process(sys.stdout) else: with open(outfile, 'w') as out: process(out)(adicionando novas linhas sempre que necessário, é claro). Definitivamente, não é muito limpo, com certeza.
Fund Monica's Lawsuit
4

Na versão 2.x, a printinstrução processa previamente o que você fornece, transformando-a em cadeias ao longo do caminho, manipulando separadores e novas linhas e permitindo o redirecionamento para um arquivo. 3.x o transforma em uma função, mas ainda tem as mesmas responsabilidades.

sys.stdout é um arquivo ou semelhante a um arquivo que possui métodos para escrever nele, que levam seqüências de caracteres ou algo nessa linha.

Ignacio Vazquez-Abrams
fonte
3

é preferível quando a impressão dinâmica é útil, por exemplo, para fornecer informações em um longo processo:

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
fonte
2
imprimir (time_msg, end = '') sys.stdout.flush vez sys.stdout.write (time_msg) () também 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 o exemplo acima:

  1. sys.stdout.writenão escreverá um objeto não-string, mas printirá

  2. sys.stdout.writenão vai adicionar um novo símbolo de linha no final, mas printvai

Se mergulharmos profundamente,

sys.stdout é um objeto de arquivo que pode ser usado para a saída de print ()

se o argumento file de print()não for especificado, sys.stdoutserá usado

GraceMeng
fonte
1

Existem situações em que sys.stdout.write () é preferível para imprimir?

Por exemplo, estou trabalhando em uma função pequena que imprime estrelas no formato de pirâmide ao passar o número como argumento, embora você possa fazer isso usando end = "" para imprimir em uma linha separada, usei sys.stdout.write em coordenação com impressão para fazer isso funcionar. Para elaborar isso, stdout.write imprime na mesma linha em que, como print, sempre imprime seu conteúdo em uma linha 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
fonte
1

Existem situações em que sys.stdout.write () é preferível para imprimir?

Descobri que o stdout funciona melhor do que imprimir em uma situação de multithreading. Uso a fila (FIFO) para armazenar as linhas a serem impressas e mantenho todas as linhas antes da linha de impressão até que minha impressão Q esteja vazia. Mesmo assim, usando print, às vezes perco o final \ n na E / S de depuração (usando o wing pro IDE).

Quando eu uso std.out com \ n na string, os formatos de E / S de depuração corretamente e os \ n são exibidos com precisão.

David Poundall
fonte
Você conhece algum motivo para o stdout funcionar melhor do que imprimir neste caso, ou isso é anedótico? Você poderia fornecer um exemplo de trabalho mínimo onde isso acontece?
user2653663
Meu pensamento é que o stdout funciona em um nível inferior ao da impressão. Definitivamente, tive corrupção de thread, pois duas rotinas de impressão estavam lutando para passar pelo stdout. Escrever para stdout um de cada thread removeu a corrupção para mim.
David Poundall
1

No Python 3, existe um motivo válido para usar a impressão sys.stdout.write, mas esse motivo também pode ser transformado em um motivo para uso sys.stdout.write.

Por esse motivo, agora print é uma função no Python 3, você pode substituir isso. Portanto, você pode usar print em qualquer lugar em um script simples e decidir que essas instruções de impressão precisam gravar stderr. Agora você pode apenas redefinir a função de impressão; pode até alterar a função de impressão global, alterando-a usando o módulo embutido. É claro que file.writevocê pode especificar o que é o arquivo, mas com a substituição da impressão, você também pode redefinir o separador de linhas ou o separador de argumentos.

O contrário é. Talvez você tenha certeza absoluta de que escreve stdout, mas também sabe que vai mudar a impressão para outra coisa, pode optar por usar sys.stdout.writee usar a impressão para registro de erros ou outra coisa.

Então, o que você usa depende de como você pretende usá-lo. printé mais flexível, mas isso pode ser um motivo para usá-lo e não usá-lo. Eu ainda optaria pela flexibilidade e escolheria imprimir. Outra razão para usar printé a familiaridade. Agora, mais pessoas entenderão o que você quer dizer com impressão e menos saberão sys.stdout.write.

Hielke Walinga
fonte
1

Uma das diferenças é a seguinte, ao tentar imprimir um byte em sua aparência hexadecimal. Por exemplo, sabemos que o valor decimal de 255está 0xFFna aparência hexadecimal:

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

sys.stdout.write(val) # prints ff2
print(val)            # prints ff
truthadjustr
fonte
Não é disso que se trata. Isso aconteceria apenas em um shell interativo e porque ... write()não adicionava \ne retorna (e exibe interativos o shell) o valor de retorno da função (número de caracteres gravados), representação hexadecimal ou qualquer outro conteúdo exibido é irrelevante.
Ondrej K.
0

No python 2, se você precisar passar por uma função, poderá atribuir os.sys.stdout.write a uma variável, não poderá fazer isso (no repl) com print.

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

Isso funciona como esperado.

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

Isso não funciona. a impressão é uma função mágica.

shanecandoit
fonte
0

Uma diferença entre printe sys.stdout.writeapontar no Python 3 também é o valor retornado quando executado no terminal. Em Python 3 sys.stdout.writeretorna o comprimento da string, enquanto printretorna apenas None.

Assim, por exemplo, executar o seguinte código interativamente no terminal imprimiria a sequência seguida pelo seu comprimento, uma vez que o comprimento é retornado e gerado quando executado interativamente:

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