Como lavar saída da função de impressão?
-
04-07-2019 - |
Pergunta
Como faço para forçar a função de impressão do Python para saída para a tela?
Esta não é uma duplicata de buffer de saída Disable - a questão vinculada está tentando sem buffer saída, enquanto que este é mais geral. As principais respostas a essa pergunta são muito poderosos ou envolvidos para um presente (eles não são boas respostas para isso), e esta questão pode ser encontrada no Google por um novato relativa.
Solução
import sys
sys.stdout.flush()
print
por impressões padrão para sys.stdout
.
Referências
Python 2
Python 3
-
print()
-
sys.stdout
- arquivo objeto - Glossário
-
io.IOBase.flush()
(herdasys.stdout
o métodoflush
deio.IOBase
)
Outras dicas
Running python -h
, vejo um opção de linha de comando :
-u: stdout binário sem buffer e stderr; também PYTHONUNBUFFERED = x consulte a página homem para obter detalhes sobre o buffer interno respeitante a 'u'
Aqui está a doc relevante.
Desde Python 3.3, você pode forçar a função normal print()
para nivelada, sem a necessidade de uso sys.stdout.flush()
; apenas definir o "rubor" argumento-chave para true. De a documentação :
print (* objetos, Set ='', end = '\ n', file = sys.stdout, lave = False)
Imprimir objetos para o arquivo corrente, separados por setembro e seguiu até o final. sep, fim e arquivo, se presente, deve ser dada como argumentos.
Todos os argumentos não-palavras-chave são convertidos em cadeias como str () faz e escrito no fluxo, separado por setembro e seguido por fim. Ambos setembro e final deve ser cadeias; eles também podem ser Nenhum, o que significa usar os valores padrão. Se nenhum objeto é dado, print () só vai acabar escrita.
O argumento do arquivo deve ser um objeto com um método de gravação (string); se ele não está presente ou Nenhum, será usado sys.stdout. saída Se é tamponado é geralmente determinada por arquivo, mas se o argumento palavra-chave flush é verdade, o fluxo é forçosamente liberado.
Como saída rubor de Python impressão?
Eu sugiro cinco maneiras de fazer isso:
- Em Python 3, chamada
print(..., flush=True)
(o argumento de descarga não está disponível em função de impressão do Python 2, e não há analógico para a instrução de impressão). - Chamada
file.flush()
no arquivo de saída (que pode envolver a função de impressão python 2 de fazer isso), por exemplo,sys.stdout
- aplicar isso a cada chamada função de impressão no módulo com uma função parcial,
print = partial(print, flush=True)
aplicada ao módulo global. - aplicar esta para o processo com uma bandeira (
-u
) passado para o interpretador de comandos - aplicar isso a cada processo de python em seu ambiente com
PYTHONUNBUFFERED=TRUE
(e retirar a variável de desfazer essa).
Python 3.3 +
Usando o Python 3.3 ou superior, você pode apenas fornecer flush=True
como um argumento de palavra-chave para a função print
:
print('foo', flush=True)
Python 2 (ou <3.3)
Eles não backport o argumento flush
para Python 2.7 Então, se você estiver usando Python 2 (ou menos de 3.3), e quer código que é compatível tanto com 2 e 3, sugiro o seguinte código de compatibilidade. (Nota da importação __future__
deve estar em / muito "perto do topo do seu módulo "):
from __future__ import print_function
import sys
if sys.version_info[:2] < (3, 3):
old_print = print
def print(*args, **kwargs):
flush = kwargs.pop('flush', False)
old_print(*args, **kwargs)
if flush:
file = kwargs.get('file', sys.stdout)
# Why might file=None? IDK, but it works for print(i, file=None)
file.flush() if file is not None else sys.stdout.flush()
O código de compatibilidade acima irá cobrir a maioria dos usos, mas para um tratamento muito mais completo, ver a six
módulo .
Como alternativa, você pode simplesmente chamar file.flush()
após a impressão, por exemplo, com a declaração de impressão em Python 2:
import sys
print 'delayed output'
sys.stdout.flush()
Alterar o padrão em um módulo para flush=True
Você pode alterar o padrão para a função de impressão utilizando functools.partial sobre o escopo global de um módulo:
import functools
print = functools.partial(print, flush=True)
Se você olhar para a nossa nova função parcial, pelo menos em Python 3:
>>> print = functools.partial(print, flush=True)
>>> print
functools.partial(<built-in function print>, flush=True)
Podemos ver que funciona como normal:
>>> print('foo')
foo
E nós pode realmente substituir o novo padrão:
>>> print('foo', flush=False)
foo
Note novamente, isso só muda o escopo global atual, porque o nome de impressão sobre o âmbito global atual irá ofuscar a função interna print
(ou excluir a referência a função de compatibilidade, se usando Python 2, em que o escopo global atual).
Se você quiser fazer isso dentro de uma função em vez de no escopo global de um módulo, você deve dar-lhe um nome diferente, por exemplo:.
def foo():
printf = functools.partial(print, flush=True)
printf('print stuff like this')
Se você declará-lo um global em uma função, você está mudando-o em espaço global do módulo, então você deve apenas colocá-lo no espaço global, a menos que o comportamento específico é exatamente o que você quer.
Alterar o padrão para o processo
Eu acho que a melhor opção aqui é usar a bandeira -u
para obter uma saída sem buffer.
$ python -u script.py
ou
$ python -um package.module
A partir da docs :
Força stdin, stdout e stderr para ser totalmente sem buffer. Em sistemas onde importa, também colocar stdin, stdout e stderr em modo binário.
Note que não há buffer interno file.readlines () e objetos de arquivo (para a linha em sys.stdin), que não é influenciada por esta opção. Para contornar isso, você vai querer usar file.readline () dentro de um tempo de 1:. Laço
Alterar o padrão para o ambiente operacional shell
Você pode obter este comportamento para todos os processos de python no ambiente ou ambientes que herdam o ambiente se você definir a variável de ambiente para um stri nonemptyng:
por exemplo, no Linux ou OSX:.
$ export PYTHONUNBUFFERED=TRUE
ou Windows:
C:\SET PYTHONUNBUFFERED=TRUE
docs :
PYTHONUNBUFFERED
Se isso for definido como uma string não-vazia é equivalente a especificar a opção -u.
Adenda
Aqui está a ajuda sobre a função do Python 2.7.12 print - nota que há não argumento flush
:
>>> from __future__ import print_function
>>> help(print)
print(...)
print(value, ..., sep=' ', end='\n', file=sys.stdout)
Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep: string inserted between values, default a space.
end: string appended after the last value, default a newline.
Além disso, como sugerido na neste blog se pode reabrir sys.stdout
no modo unbuffered:
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
Cada operação stdout.write
e print
será automaticamente liberado mais tarde.
Com Python 3.x a função print()
foi estendida:
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
Assim, você pode apenas fazer:
print("Visiting toilet", flush=True)
Usando a opção -u
de linha de comando funciona, mas é um pouco desajeitado pouco. Isso significaria que o programa poderia se comportar de forma incorreta se o usuário invocado o script sem a opção -u
. Eu costumo usar um stdout
costume, como este:
class flushfile:
def __init__(self, f):
self.f = f
def write(self, x):
self.f.write(x)
self.f.flush()
import sys
sys.stdout = flushfile(sys.stdout)
... Agora todas as suas chamadas print
(que usam sys.stdout
implicitamente), será flush
ed automaticamente.
Por que não tentar usar um arquivo sem buffer?
f = open('xyz.log', 'a', 0)
ou
sys.stdout = open('out.log', 'a', 0)
A idéia de Dan não funciona muito bem:
#!/usr/bin/env python
class flushfile(file):
def __init__(self, f):
self.f = f
def write(self, x):
self.f.write(x)
self.f.flush()
import sys
sys.stdout = flushfile(sys.stdout)
print "foo"
O resultado:
Traceback (most recent call last):
File "./passpersist.py", line 12, in <module>
print "foo"
ValueError: I/O operation on closed file
Eu acredito que o problema é que ele herda da classe de arquivo, o que realmente não é necessário. De acordo com a documentação para sys.stdout:
stdout e stderr necessidade não ser embutido arquivo de objetos: qualquer objeto é aceitável enquanto ele tem um método write () que leva um argumento de cadeia.
para mudar
class flushfile(file):
para
class flushfile(object):
faz com que funcione muito bem.
Aqui é a minha versão, que fornece writelines () e fileno (), também:
class FlushFile(object):
def __init__(self, fd):
self.fd = fd
def write(self, x):
ret = self.fd.write(x)
self.fd.flush()
return ret
def writelines(self, lines):
ret = self.writelines(lines)
self.fd.flush()
return ret
def flush(self):
return self.fd.flush
def close(self):
return self.fd.close()
def fileno(self):
return self.fd.fileno()
Em Python 3 você pode substituir a função de impressão com o conjunto padrão para flush = True
def print(*objects, sep=' ', end='\n', file=sys.stdout, flush=True):
__builtins__.print(*objects, sep=sep, end=end, file=file, flush=flush)
Eu fiz isso como esta em Python 3.4:
'''To write to screen in real-time'''
message = lambda x: print(x, flush=True, end="")
message('I am flushing out now...')