Question Comment vider la sortie de la fonction d'impression?


Comment forcer la fonction d'impression de Python à sortir vers l'écran?

Ce n'est pas un duplicata de Désactiver la mise en tampon de sortie - La question liée tente d'extraire sans tampon, alors que c'est plus général. Les meilleures réponses dans cette question sont trop puissantes ou impliquées pour celui-ci (ils ne sont pas de bonnes réponses pour cela), et cette question peut être trouvée sur Google par un débutant relatif.


886
2017-10-23 17:59


origine


Réponses:


import sys
sys.stdout.flush()

Imprimer par défaut imprime à sys.stdout.

Les références:


1049
2017-10-23 18:04



Fonctionnement python -h, Je vois un option de ligne de commande:

-u: stdout binaire sans tampon et stderr; aussi PYTHONUNBUFFERED = x            voir la page man pour plus de détails sur la mise en mémoire tampon interne relative à '-u'

Voici la document pertinent.


292
2017-10-23 18:06



Depuis Python 3.3, vous pouvez forcer la normale print() fonction pour vider sans avoir besoin d'utiliser sys.stdout.flush(); il suffit de mettre l'argument "flush" à true. De La documentation:

print (* objets, sep = '', end = '\ n', fichier = sys.stdout, flush = Faux)

Imprimer les objets dans le fichier de flux, séparés par sep et suivis de la fin. sep, fin et fichier, s'ils sont présents, doivent être donnés en tant qu'arguments-clés.

Tous les arguments non-mot-clé sont convertis en chaînes comme str () et écrits dans le flux, séparés par sep et suivis par end. Les deux sep et fin doivent être des ficelles; ils peuvent aussi être None, ce qui signifie utiliser les valeurs par défaut. Si aucun objet n'est donné, print () écrira juste end.

L'argument du fichier doit être un objet avec une méthode write (string); s'il n'est pas présent ou None, sys.stdout sera utilisé. Que la sortie soit mise en mémoire tampon est généralement déterminée par le fichier, mais si l'argument du mot clé flush est vrai, le flux est vidé de force.


244
2018-04-17 20:10



Comment vider la sortie de l'impression Python?

Je suggère cinq façons de le faire:

  • En Python 3, appelez print(..., flush=True) (l'argument flush n'est pas disponible dans la fonction d'impression de Python 2 et il n'y a pas d'équivalent pour l'instruction print).
  • Appel file.flush() sur le fichier de sortie (nous pouvons envelopper la fonction d'impression de python 2 pour ce faire), par exemple, sys.stdout
  • appliquer ceci à chaque appel de fonction d'impression dans le module avec une fonction partielle,
    print = partial(print, flush=True) appliqué au module global.
  • appliquer ceci au processus avec un drapeau (-u) passé à la commande d'interprète
  • appliquer ceci à tous les processus python dans votre environnement avec PYTHONUNBUFFERED=TRUE (et désactiver la variable pour annuler cela).

Python 3.3+

En utilisant Python 3.3 ou supérieur, vous pouvez simplement fournir flush=True comme un argument clé de la print fonction:

print('foo', flush=True) 

Python 2 (ou <3.3)

Ils n'ont pas rétroporté le flush argument à Python 2.7 Donc si vous utilisez Python 2 (ou moins de 3.3), et que vous voulez du code compatible avec les 2 et 3, je vous suggère le code de compatibilité suivant. (Noter la __future__l'importation doit être à / très "près de haut de votre module"):

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

Le code de compatibilité ci-dessus couvrira la plupart des utilisations, mais pour un traitement beaucoup plus approfondi, voir le six module.

Alternativement, vous pouvez simplement appeler file.flush() après l'impression, par exemple, avec l'instruction print dans Python 2:

import sys
print 'delayed output'
sys.stdout.flush()

Changer la valeur par défaut dans un module pour flush=True

Vous pouvez modifier la valeur par défaut de la fonction d'impression en utilisant functools.partial sur la portée globale d'un module:

import functools
print = functools.partial(print, flush=True)

si vous regardez notre nouvelle fonction partielle, au moins en Python 3:

>>> print = functools.partial(print, flush=True)
>>> print
functools.partial(<built-in function print>, flush=True)

Nous pouvons voir que cela fonctionne comme d'habitude:

>>> print('foo')
foo

Et nous pouvons réellement remplacer la nouvelle valeur par défaut:

>>> print('foo', flush=False)
foo

Notez à nouveau que cela ne modifie que la portée globale actuelle, car le nom de l'impression sur la portée globale actuelle éclipse le code interne. print function (ou déréférencer la fonction de compatibilité, si vous utilisez Python 2, dans cette portée globale actuelle).

Si vous voulez le faire à l'intérieur d'une fonction plutôt que sur la portée globale d'un module, vous devez lui donner un nom différent, par exemple:

def foo():
    printf = functools.partial(print, flush=True)
    printf('print stuff like this')

Si vous le déclarez global dans une fonction, vous le changez dans l'espace de noms global du module, vous devriez donc simplement le placer dans l'espace de noms global, à moins que ce comportement spécifique ne corresponde exactement à ce que vous voulez.

Changer la valeur par défaut pour le processus

Je pense que la meilleure option ici est d'utiliser le -u drapeau pour obtenir une sortie sans tampon.

$ python -u script.py

ou

$ python -um package.module

Du docs:

Forcer stdin, stdout et stderr à être totalement unbuffered. Sur les systèmes où cela compte, mettez aussi stdin, stdout et stderr en mode binaire.

Notez qu'il existe une mise en mémoire tampon interne dans file.readlines () et File Objects (pour line dans sys.stdin) qui n'est pas influencée par cette option. Pour contourner ce problème, vous devrez utiliser file.readline () dans un while 1: loop.

Modification de la valeur par défaut pour l'environnement d'exploitation shell

Vous pouvez obtenir ce comportement pour tous les processus python dans l'environnement ou les environnements qui héritent de l'environnement si vous définissez la variable d'environnement sur une chaîne non vide:

par exemple, sous Linux ou OSX:

$ export PYTHONUNBUFFERED=TRUE

ou Windows:

C:\SET PYTHONUNBUFFERED=TRUE

du docs:

PYTHONUNBUFFERED

Si cela est défini sur une chaîne non vide, cela équivaut à spécifier l'option -u.


Addenda

Voici l'aide sur la fonction d'impression de Python 2.7.12 - notez qu'il y a non  flush argument:

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

100
2018-02-17 21:01



Aussi comme suggéré dans ce blog on peut rouvrir sys.stdout en mode sans tampon:

sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

Chaque stdout.write et print l'opération sera automatiquement rincée par la suite.


65
2018-02-27 08:38



En utilisant le -u Commutateur de ligne de commande fonctionne, mais il est un peu maladroit. Cela signifierait que le programme se comporterait de façon incorrecte si l'utilisateur invoquait le script sans -u option. J'utilise habituellement une coutume stdout, comme ça:

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)

... Maintenant tout votre print appels (qui utilisent sys.stdout implicitement), sera automatiquement flushéd.


30
2017-10-23 19:54



Avec Python 3.x ils ont étendu le print()fonction:

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

Donc, vous pouvez simplement faire:

print("Visiting toilet", flush=True)

Entrée Python Docs


22
2017-10-21 17:23



Pourquoi ne pas essayer d'utiliser un fichier sans tampon?

f = open('xyz.log', 'a', 0)

OU

sys.stdout = open('out.log', 'a', 0)

17
2018-04-12 10:57



import sys
print 'This will be output immediately.'
sys.stdout.flush()

12
2017-12-12 07:46



L'idée de Dan ne marche pas tout à fait:

#!/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"

Le résultat:

Traceback (most recent call last):
  File "./passpersist.py", line 12, in <module>
    print "foo"
ValueError: I/O operation on closed file

Je crois que le problème est qu'il hérite de la classe de fichier, ce qui n'est pas vraiment nécessaire. Selon les docs pour sys.stdout:

stdout et stderr ne doivent pas être intégrés   objets de fichiers: tout objet est acceptable   tant qu'il a une méthode write ()   cela prend un argument de chaîne.

tellement changeant

class flushfile(file):

à

class flushfile(object):

ça marche très bien.


10
2017-11-13 22:15