Como descarregar a saída da função de impressão?
como é que obrigo a função de impressão do Python a sair para o ecrã?
Isto não é um duplicado de desactivar o 'buffer' de saída - a questão ligada está a tentar um resultado não-barrado, enquanto isto é mais geral. As respostas de topo nessa pergunta são muito poderosas ou envolvidas para este (eles não são boas respostas para isso), e esta pergunta pode ser encontrada no Google por um novato relativo.
14 answers
import sys
sys.stdout.flush()
Imprimir por omissão as impressões em sys.stdout
.
Referências:
Em execução python -h
, vejo uma opção da linha de comandos :
- u: stdout binário não-sufferido e stderr; também PYTHONUNBUFFERED = x veja a página do homem para mais detalhes sobre o '- u '
Aqui está o relevante doc .
Desde o Python 3. 3, você pode forçar a função normal print()
a puxar o autoclismo sem a necessidade de usar sys.stdout.flush()
; Basta definir o argumento da palavra-chave "flush" como verdadeiro. Da documentação:
Print (*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
Imprimir os objectos no ficheiro stream, separados por sep e seguidos pelo fim. sep, end e file, se estiverem presentes, devem ser indicados como argumentos de palavra-chave.
Todos os argumentos sem palavras-chave são convertidos para strings como str () faz e escreve para o fluxo, separado por sep e seguido por fim. Tanto sep quanto end devem ser strings; eles também podem ser nenhum, o que significa usar os valores padrão. Se não forem indicados objectos, print () irá apenas escrever o fim.
O argumento do ficheiro deve ser um objecto com um método de escrita( string); se não estiver presente ou nenhum, sys.stdout será usado. Se o resultado é buffer é normalmente determinado por ficheiro, mas se o argumento da palavra-chave flush for verdadeiro, o fluxo é corado à força.
Sugiro cinco maneiras de fazer isto:Como descarregar o resultado da impressão em Python?
- em Python 3, call
print(..., flush=True)
(o argumento flush não está disponível na função de impressão do Python 2, e não existe nenhum análogo para a declaração de impressão). - chamada
file.flush()
no ficheiro de saída( podemos embrulhar a função de impressão do python 2 para fazer isto), por exemplo,sys.stdout
- aplica isto a cada chamada de função de impressão no módulo com uma função parcial,
print = partial(print, flush=True)
aplicado ao módulo global. - aplica isto ao processo com uma bandeira (
-u
) passada ao comando interpretador - aplique isto em todos os processos python do seu ambiente com
PYTHONUNBUFFERED=TRUE
(e desligue a variável para desfazer isto).
Python 3. 3+
Usando o Python 3. 3 ou superior, poderá apenas fornecer flush=True
como argumento de palavra-chave para a função print
:
print('foo', flush=True)
Python 2 (ou
Eles não alteraram o argumento flush
para o Python 2.7 Então, se você está usando Python 2 (ou menos de 3.3), e quer um código compatível com 2 e 3, posso sugerir o seguinte código de compatibilidade. (Note que __future__
a importação deve ser 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 referido abrangerá a maioria das utilizações, mas para um tratamento muito mais completo, ver o módulo six
.
Em alternativa, pode simplesmente ligar para file.flush()
depois de imprimir, por exemplo, com a declaração de impressão em Python 2:
import sys
print 'delayed output'
sys.stdout.flush()
Mudar o valor por omissão num módulo para flush=True
Pode alterar o valor por omissão para a função de impressão usando o functools.parcial no âmbito 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 o normal.
>>> print('foo')
foo
E podemos anular o novo padrão.
>>> print('foo', flush=False)
foo
Note novamente, isto só altera o âmbito global actual, porque o nome da impressão no escopo global atual irá ofuscar a função builtin print
(ou dereference a função de compatibilidade, se usando Python 2, nesse escopo global atual).
Se quiser fazer isto dentro de uma função em vez de no âmbito global de um módulo, deve dar-lhe um nome diferente, por exemplo:
def foo():
printf = functools.partial(print, flush=True)
printf('print stuff like this')
Se o declarar global numa função, está a alterá-lo no espaço de nomes global do módulo, por isso deve colocá-lo no espaço de nomes global, a menos que esse comportamento específico é exactamente o que queres.
Alterar o valor por omissão para o processo
Acho que a melhor opção é usar a bandeira para obter uma saída livre.$ python -u script.py
Ou
$ python -um package.module
Forçar o stdin, o stdout e o stderr a não serem baralhados. Em sistemas onde isso importa, também coloque stdin, stdout e stderr em modo binário.Note que há 'buffering' interno no ficheiro.objectos de leitura() e ficheiros (para linha em sys.stdin) que não é influenciado por esta opção. Para trabalhar em torno disso, você vai querer usar arquivo.readline () inside a while 1: loop.
Alterar o valor por omissão para o ambiente operacional da shell
Poderá obter este comportamento para todos os processos python no ambiente ou ambientes que herdam do ambiente se definir a variável de ambiente como uma cadeia de caracteres não vazia:
Por exemplo, em Linux ou OSX:
$ export PYTHONUNBUFFERED=TRUE
Ou Windows:
C:\SET PYTHONUNBUFFERED=TRUE
PYTHONUNBUFFERED
Se este for definido como um texto não-vazio, é equivalente a indicar a opção-U.
Adenda
Aqui está a ajuda na função de impressão do Python 2.7.12-note que existe Não flush
argumento:
>>> 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.
Também como sugerido em Este blog pode-se reabrir sys.stdout
em modo livre:
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
Cada operação stdout.write
e print
será automaticamente descarregada depois.
Usar o interruptor da linha de comandos -u
funciona, mas é um pouco desajeitado. Isso significaria que o programa poderia comportar-se incorretamente se o usuário invocasse o script sem a opção -u
. Eu normalmente uso um costume stdout
, como este:
class flushfile(object):
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ão automaticamente flush
ed.
Com Python 3.x eles estenderam a função print()
:
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
Então, podes fazer:
print("Visiting toilet", flush=True)
Porque não tentar usar um ficheiro livre?
f = open('xyz.log', 'a', 0)
Ou
sys.stdout = open('out.log', 'a', 0)
import sys
print 'This will be output immediately.'
sys.stdout.flush()
#!/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 arquivos, o que na verdade não é necessário. De acordo com os documentos da sys.stdout:
O Stdout e o stderr não precisam de ser incorporados. objectos do ficheiro: qualquer objecto é aceitável desde que tenha um método de escrita() é preciso um argumento.
Tão variável
class flushfile(file):
A
class flushfile(object):
Faz com que funcione bem.
Aqui está 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()
import io,sys
class flushfile:
def __init__(self, f):
self.f = f
def write(self, x):
self.f.write(x)
self.f.flush()
sys.stdout = flushfile(sys.stdout)
No Python 3, poderá sobrepor a função de impressão com o conjunto predefinido 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)
'''To write to screen in real-time'''
message = lambda x: print(x, flush=True, end="")
message('I am flushing out now...')