web-dev-qa-db-fra.com

impression de surcharge python

Suis-je capable de surcharger la fonction print et d'appeler la fonction normale de l'intérieur? Ce que je veux faire, c'est après une ligne spécifique, je veux que print appelle mon print qui appellera la normale print et écrit une copie dans un fichier.

Je ne sais pas non plus comment surcharger print. Je ne sais pas comment faire des arguments de longueur variable. Je vais le chercher bientôt mais surcharge python d'impression vient de me dire que je ne peux pas surcharger print dans 2.x qui est ce que j'utilise.

41
user34537

Pour ceux qui examinent les réponses précédemment datées, à partir de la version "Python 2.6", il y a une nouvelle réponse à la question de l'affiche originale.

Dans Python 2.6 et plus, vous pouvez désactiver l'instruction print en faveur de la fonction print, puis remplacer la fonction print par votre propre fonction print:

from __future__ import print_function
# This must be the first statement before other statements.
# You may only put a quoted or triple quoted string, 
# Python comments, other future statements, or blank lines before the __future__ line.

try:
    import __builtin__
except ImportError:
    # Python 3
    import builtins as __builtin__

def print(*args, **kwargs):
    """My custom print() function."""
    # Adding new arguments to the print function signature 
    # is probably a bad idea.
    # Instead consider testing if custom argument keywords
    # are present in kwargs
    __builtin__.print('My overridden print() function!')
    return __builtin__.print(*args, **kwargs)

Bien sûr, vous devez tenir compte du fait que cette fonction d'impression ne concerne que le module à ce stade. Vous pouvez choisir de remplacer __builtin__.print, mais vous devrez enregistrer l'original __builtin__.print; probablement déblayage avec le __builtin__ espace de noms.

59
DevPlayer

La surcharge print est une fonctionnalité de conception de python 3.0 pour remédier à votre manque de capacité à le faire dans python 2.x.

Cependant, vous pouvez remplacer sys.stdout. ( exemple .) Affectez-le simplement à un autre objet de type fichier qui fait ce que vous voulez.

Alternativement, vous pouvez simplement diriger votre script via la commande unix tee. python yourscript.py | tee output.txt sera imprimé à la fois sur stdout et sur output.txt, mais cela capturera toutes les sorties.

31
ʞɔıu

J'ai rencontré le même problème.

Que dis-tu de ça:

class writer :
    def __init__(self, *writers) :
        self.writers = writers

    def write(self, text) :
        for w in self.writers :
            w.write(text)

import sys

saved = sys.stdout
fout = file('out.log', 'w')
sys.stdout = writer(sys.stdout, fout)
print "There you go."
sys.stdout = saved
fout.close()

Cela a fonctionné comme un charme pour moi. Il a été tiré de http://mail.python.org/pipermail/python-list/2003-F February/188788.html

10
Afrobeard
class MovieDesc:
    name = "Name"
    genders = "Genders"
    country = "Country"

 def __str__(self):
#Do whatever you want here
        return "Name: {0}\tGenders: {1} Country: {2} ".format(self.name,self.genders,self.country)

)
9
Kvant

Bien que vous ne puissiez pas remplacer le mot clé print (dans Python 2.x print est un mot clé), il est courant de remplacer sys.stdout pour faire quelque chose de similaire à print surcharger; par exemple, avec une instance de StringIO.StringIO. Cela capturera toutes les données imprimées dans l'instance StringIO, après quoi vous pourrez les manipuler.

3
cdleary

En Python 2.x vous ne pouvez pas, car print n'est pas une fonction, c'est une déclaration. En Python 3 print est une fonction, donc je supposons qu'il puisse être outrepassé (je ne l'ai pas essayé, cependant).

2
Joonas Pulakka

Pour un exemple très simple, à partir de Python3.4 (non testé avec des versions plus anciennes) cela fonctionne bien pour moi (placé en haut du module):

import time
def dprint(string):
  __builtins__.print("%f -- %s" % (time.time(), string))

print = dprint

Remarque, cela ne fonctionne que si le paramètre de chaîne est une chaîne ... YMMV

1
Troy E. Lanes

pensais juste que j'ajouterais mon idée ... convenait à mes objectifs de pouvoir exécuter sthg dans Eclipse, puis exécuter à partir de l'interface de ligne de commande (Windows) sans obtenir d'exceptions d'encodage avec chaque instruction d'impression. Quoi que vous fassiez, ne faites pas d'EncodingStdout une sous-classe du fichier de classe: la ligne "self.encoding = encoding" entraînerait alors l'attribut d'encodage étant None!

NB une chose que j'ai découverte au cours d'une journée aux prises avec ce genre de choses est que l'exception d'encodage est levée AVANT d'arriver à "imprimer" ou "écrire": c'est lorsque la chaîne paramétrée (c'est-à-dire "mondodod% s blah blah% s"% ( "blip", "blap")) est construit par ... quoi ??? le "cadre"?

class EncodingStdout( object ):
    def __init__( self, encoding='utf-8' ):
        self.encoding = encoding

    def write_ln( self, *args ):
        if len( args ) < 2:
            sys.__stdout__.write( args[ 0 ] + '\n' )
        else:
            if not isinstance( args[ 0 ], basestring ):
                raise Exception( "first arg was %s, type %s" % ( args[ 0 ], type( args[ 0 ]) ))
            # if the default encoding is UTF-8 don't bother with encoding
            if sys.getdefaultencoding() != 'utf-8':
                encoded_args = [ args[ 0 ] ]
                for i in range( 1, len( args )):
                    # numbers (for example) do not have an attribute "encode"
                    if hasattr( args[ i ], 'encode' ):
                        encoded_args.append( args[ i ].encode( self.encoding, 'replace' ) )
                    else:
                        encoded_args.append( args[ i ])
                args = encoded_args
            sys.__stdout__.write( args[ 0 ] % Tuple( args[ 1 : ] ) + '\n' )
        # write seems to need a flush
        sys.__stdout__.flush()

    def __getattr__( self, name ):
        return sys.__stdout__.__getattribute__( name )

print "=== A mondodod %s %s" % ( "été", "pluviôse, irritée contre la ville entière" ) 


sys.stdout = EncodingStdout()
sys.stdout.write_ln( "=== B mondodod %s %s", "été", "pluviôse, irritée contre la ville entière" )

# convenience method
def pr( *args ):
    sys.stdout.write_ln( *args )

pr( "=== C mondodod %s %s", "été", "pluviôse, irritée contre la ville entière" )
1
mike rodent

J'ai répondu à la même question sur une autre SO question

Essentiellement, la solution la plus simple consiste à simplement rediriger la sortie vers stderr comme suit, dans le fichier de configuration wsgi.

sys.stdout = sys.stderr
1
Lakshman Prasad