Comment éliminer la sortie de la fonction d'impression?

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

ce n'est pas un duplicata de disable output buffering - la question liée tente une sortie non tamponnée, alors que c'est plus général. Les meilleures réponses à cette question sont trop puissantes ou impliquées pour celle-ci (ce ne sont pas de bonnes réponses pour cela), et cette question peut être trouvée sur Google par un internaute novice relatif.

915
demandé sur martineau 2008-10-23 21:59:39

14 réponses

1083
répondu CesarB 2016-01-08 03:38:23

Running python -h , je vois une option de ligne de commande :

-u : non-binaires, stdout et stderr; aussi PYTHONUNBUFFERED=x voir la page de manuel pour plus de détails sur les tampons internes relatifs à' - u '

voici le doc pertinent .

295
répondu gimel 2008-10-23 18:06:49

depuis Python 3.3, vous pouvez forcer la fonction normale print() à tirer la chasse sans avoir besoin d'utiliser sys.stdout.flush() ; il suffit de mettre l'argument de mot-clé "flush" à true. De la documentation :

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

objets d'Impression pour le fichier de flux, séparés par la sep et suivi par la fin. sep, fin de fichier et, le cas échéant, doivent être donné comme mot-clé arguments.

tous les arguments sans mot-clé sont convertis en chaînes comme str() does et écrits dans le flux, séparés par sep et suivis par end. Sep et end doivent être des chaînes de caractères; ils peuvent aussi être None, ce qui signifie utiliser les valeurs par défaut. Si aucun objet n'est donné, print() écrira simplement end.

l'argument file doit être un objet avec une méthode write(string); s'il n'est pas présent ou aucun, sys.la sortie standard sera utilisé. si la sortie est tamponnée est généralement déterminée par le fichier, mais si l'argument du mot-clé flush est vrai, le flux est évacué de force.

250
répondu Eugene Sajine 2014-10-22 00:32:20

comment débusquer la sortie de l'impression Python?

je suggère cinq façons de faire ceci:

  • 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 d'impression).
  • appeler file.flush() sur le fichier de sortie (nous pouvons envelopper la fonction d'impression de python 2 pour le 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 de l'interprète
  • appliquez ceci à chaque processus python dans votre environnement avec PYTHONUNBUFFERED=TRUE (et désactivez la variable pour annuler ceci).

Python 3.3+

en utilisant Python 3.3 ou supérieur, vous pouvez simplement fournir flush=True comme argument de mot-clé à la fonction print :

print('foo', flush=True) 

Python 2 (ou < 3.3)

ils n'ont pas rétroporté l'argument flush à Python 2.7 donc si vous utilisez Python 2 (ou moins que 3.3), et que vous voulez du code qui est compatible avec 2 et 3, Puis-je suggérer le code de compatibilité suivant. (Note: l'importation de __future__ doit être at/très "près de la 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 complet, voir le six module .

alternativement, vous pouvez simplement appeler file.flush() après l'impression, par exemple, avec la déclaration d'impression en Python 2:

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

changer la valeur par défaut dans un module en flush=True

vous pouvez changer la valeur par défaut de la fonction d'impression en utilisant des functools.partielle 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 en fait annuler le nouveau défaut:

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

noter encore, ce seul modifie la portée globale actuelle, parce que le nom d'impression sur la portée globale actuelle éclipsera la fonction print (ou déréférenciera la fonction de compatibilité, si vous utilisez Python 2, dans cette portée globale actuelle).

si vous voulez faire cela à l'intérieur d'une fonction au lieu de 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 sur le l'espace de noms global du module, donc vous devriez simplement le mettre dans l'espace de noms global, à moins que ce comportement spécifique soit 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 drapeau -u pour obtenir la sortie libre.

$ python -u script.py

ou

$ python -um package.module

De la docs :

forcer stdin, stdout et stderr à être totalement débuffrés. Sur les systèmes où c'est important, mettez aussi stdin, stdout et stderr en mode binaire.

notez qu'il y a un tampon interne dans le fichier.readlines() et les Objets de Fichier (par ligne dans sys.stdin) qui n'est pas influencée par cette option. Pour contourner cela, vous voudrez utiliser file.readline() à l'intérieur d'un tout en 1: boucle.

changer la valeur par défaut pour l'interpréteur de commandes environnement

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 à une chaîne non vide:

p.ex. sous Linux ou OSX:

$ export PYTHONUNBUFFERED=TRUE

ou Windows:

C:\SET PYTHONUNBUFFERED=TRUE

de la docs :

PYTHONUNBUFFERED

si cette option est définie à une chaîne non vide, elle est équivalente à l'option-U.


Addendum

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.
112
répondu Aaron Hall 2018-06-08 00:43:04

aussi comme suggéré dans ce blog on peut rouvrir sys.stdout en mode non tamponné:

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

chaque opération stdout.write et print sera automatiquement vidangée par la suite.

65
répondu Antony Hatchkins 2012-04-01 16:25:12

avec le commutateur de ligne de commande -u fonctionne, mais il est un peu maladroit. Cela signifierait que le programme pourrait se comporter incorrectement si l'utilisateur invoquait le script sans l'option -u . J'utilise habituellement un stdout personnalisé, comme ceci:

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, tous vos appels print (qui utilisent implicitement sys.stdout ), seront automatiquement flush ed.

31
répondu Dan Lenski 2016-11-04 19:51:33

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

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

donc, vous pouvez juste faire:

print("Visiting toilet", flush=True)

Python Docs Entrée

30
répondu Noah Krasser 2018-06-30 11:50:10

pourquoi ne pas essayer d'utiliser un fichier non tamponné?

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

ou

sys.stdout = open('out.log', 'a', 0)
17
répondu Nakilon 2012-06-13 07:43:45
import sys
print 'This will be output immediately.'
sys.stdout.flush()
12
répondu Dynamic 2011-12-12 07:51:57

Dan l'idée de ne 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 file, ce qui n'est pas nécessaire. Selon le docs pour sys.stdout:

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

modifier

class flushfile(file):

à

class flushfile(object):

le rend parfait.

10
répondu Kamil Kisiel 2008-11-13 22:22:20

Voici ma version, qui fournit writelines() et fileno(), aussi:

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()
6
répondu guettli 2015-03-21 15:36:58

a adoré la solution de Dan! Pour python3:

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)
5
répondu Jonas Byström 2013-01-15 18:19:42

dans Python 3, vous pouvez remplacer la fonction d'impression par défaut définie à flush = True

def print(*objects, sep=' ', end='\n', file=sys.stdout, flush=True):
    __builtins__.print(*objects, sep=sep, end=end, file=file, flush=flush)
2
répondu user263387 2016-05-15 19:13:34

Je l'ai fait comme ceci en Python 3.4:

'''To write to screen in real-time'''
message = lambda x: print(x, flush=True, end="")
message('I am flushing out now...')
2
répondu kmario23 2016-08-15 15:22:01