2009-02-15 15 views
35

¿Puedo sobrecargar la función print y llamar a la función normal desde adentro? Lo que quiero hacer es después de una línea específica que quiero print llamar a mi print que llamará al print normal y escribir una copia en el archivo.sobrecarga print python

Además, no sé cómo sobrecargar print. No sé cómo hacer argumentos de longitud variable. Lo buscaré pronto pero overload print python me acaba de decir que no puedo sobrecargar print en 2.x que es lo que estoy usando.

Respuesta

2

En Python 2.x no puede, porque imprimir no es una función, es una afirmación. En Python 3 imprimir es una función, por lo que supongo que podría ser anulada (aunque no lo haya probado).

31

Sobrecarga print es una característica de diseño de python 3.0 para abordar su falta de capacidad para hacerlo en python 2.x.

Sin embargo, puede anular sys.stdout. (example.) Simplemente asignes a otro objeto similar a un archivo que hace lo que quieres.

Como alternativa, puede simplemente hacer que su script pase por el comando unix tee. python yourscript.py | tee output.txt se imprimirá tanto en stdout como en output.txt, pero esto capturará todos los resultados.

3

Aunque no se puede reemplazar la palabra clave print (en Python 2.x print es una palabra clave), es una práctica común sustituir sys.stdout hacer algo similar a print primordial; por ejemplo, con una instancia de StringIO.StringIO. Esto capturará todos los datos impresos en la instancia StringIO, luego de lo cual podrá manipularlo.

10

Me encontré con el mismo problema.

¿Qué tal esto:

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

funcionó como un encanto para mí. Fue tomado de http://mail.python.org/pipermail/python-list/2003-February/188788.html

+3

'saved = sys.stdout' no es necesario,' sys .__ stdout__' siempre contiene el 'stdout' original, por lo que al final simplemente' sys.stdout = sys .__ stdout__'. – chown

+0

guardar el sys.stdout le permite encadenar sobrescrituras; si escribe directamente en sys .__ stdout__ omitirá cualquier marco de trabajo de registro o tal que intente e inyecte en el programa. Lo mejor es guardar explícitamente el valor anterior de stdout. – Will

+0

¿Hay alguna razón en particular para abrir el registro usando 'file()' en lugar de 'open()'? [La documentación no recomienda eso.] (Https://docs.python.org/2/library/functions.html#file) – Eric

1

respondí la misma pregunta on a different SO question

Esencialmente, la solución más sencilla es simplemente redirigir la salida a stderr de la siguiente manera, en el archivo de configuración wsgi.

sys.stdout = sys.stderr 
50

Para aquellos que revisan las respuestas anteriores, a partir del lanzamiento de la versión "Python 2.6" hay una nueva respuesta a la pregunta del cartel original.

En Python 2.6 y arriba, puede desactivar la declaración de impresión a favor de la función de impresión, y luego anular la función de impresión con su propia función de impresión:

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) 

Por supuesto, usted debe tener en cuenta que esta función de impresión solo abarca todo el módulo en este punto. Puede elegir anular __builtin__.print, pero deberá guardar el __builtin__.print original; probablemente se esté volcando con el espacio de nombre __builtin__.

+0

Si intento usar esta función en Python 2.7.3 obtengo una 'línea 7, en impresión return __builtins __. Print (* args, ** kwargs) AttributeError: el objeto 'dict' no tiene ningún atributo 'print'' error. ¿Cual podría ser el problema? – loudandclear

+0

Hmmm ... Lo probé con Python 2.7.2 y funcionó. He notado que Python 2.7.4 acaba de ser lanzado y hay algunas correcciones de errores con _ _future _ _ e print_function Revisa http://hg.python.org/cpython/file/9290822f2280/Misc/NEWS No he probado 2.7.4 cualquiera. – DevPlayer

+2

Debería hacer 'import __builtin__' y luego' __builtin __. Print' en lugar de usar '__builtins__', [consulte la explicación aquí] (https://docs.python.org/2/reference/executionmodel.html). – rczajka

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

) 
1

pensé en agregar mi idea ...se adaptaba a mis propósitos de poder ejecutar sthg en Eclipse y luego ejecutar desde la CLI (Windows) sin obtener excepciones de codificación con cada instrucción de impresión. Hagas lo que hagas, no hagas que EncodingStdout sea una subclase de archivo de clase: la línea "self.encoding = encoding" daría como resultado que el atributo de codificación sea None.

NB Una cosa que descubrí durante un día lidiando con esto es que la excepción de codificación se levanta ANTES de llegar a "imprimir" o "escribir": es cuando la cadena parametrizada (es decir, "mondodod% s blah blah% s "% (" blip "," blap ")) está construido por ... ¿qué? el marco"?

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

Para un ejemplo muy simple, a partir de Python3.4 (no se han probado con versiones anteriores) esto funciona bien para mí (que se encuentra en la parte superior del módulo):

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

print = dprint 

Nota, este solo funciona si el parámetro de cadena es un str ... YMMV