2011-08-10 8 views
6

Pensé que la instrucción print acaba de llamar al método .write() en el objeto sys.stdout (por defecto).pitthons 'print' declaración no llama al método .write()?

pero después de haber escrito una subclase de esta manera:

import time 

class logfile(file): 
    def __init__(self, *args, **kwargs): 
     file.__init__(self, *args, **kwargs) 

    def write(self, logstr): 
     if logstr[-1] != '\n': logstr += '\n' 
     super(logfile, self).write(time.strftime('%D-%T ') + str(logstr)) 

Parece que funciona si creo un objeto logfile y llame al método write, pero cuando se trata de cambiar el objeto sys.stdout a una instancia de la logfile se aparece como si print no está llamando al write. ¿Tal vez writelines?

El uso de este:

#!/usr/bin/python 

from myfile import logfile 
import sys 

sys.stdout = logfile('somefile', 'w') 

print 'this is a test' 
sys.stdout.write('this is another test') 

Mi archivo de salida 'somefile' contiene:

this is a test 
08/10/11-16:59:47 this is another test 

se puede ver la primera línea en el archivo de salida es lo que traté de print y la segunda línea se qué se usó en sys.stdout.write

Pensé print simplemente llamé write method- claramente me falta tan mething básico.

+0

¿Ayuda http://stefaanlippens.net/redirect_python_print? – Evpok

+1

'print' tiene su propia referencia a' stdout'. – agf

+0

@Evpok Creo que si intenta redirigir la impresión en lugar de utilizar el registro normal, probablemente no quiera modificar las declaraciones de 'impresión 'preexistentes. – agf

Respuesta

4

Aparentemente, esta es una limitación de la implementación de Python 2 donde print es una declaración en lugar de una expresión con efectos secundarios (como en Python 3).

Reescribí el código para algo que funciona en Python 3:

from io import FileIO 
import time 

class logfile(FileIO): 
    def __init__(self, *args, **kwargs): 
    FileIO.__init__(self, *args, **kwargs) 

    def write(self, logstr): 
    if logstr[-1] == '\n': logstr = logstr[:-1] 
    super(logfile, self).write(bytes(time.strftime('%D-%T ') + str(logstr), 'UTF-8')) 

import sys 

sys.stdout = logfile('somefile', 'w') 

print("This is a test") 
sys.stdout.write('this is another test') 

Por lo que yo sé que no hay manera de crear el mismo comportamiento en Python 2.

También he intentado usar from __future__ import print_function pero eso no hizo diferencia.

2

Si coloca el archivo en una variable de instancia, parece que funciona.

import time 

class logfile(object): 
    def __init__(self, *args, **kwargs): 
     self.f = file(*args, **kwargs) 
    def write(self, logstr): 
     if logstr[-1] != '\n': logstr += '\n' 
     self.f.write(time.strftime('%D-%T ') + str(logstr)) 

Desafortunadamente registra líneas en vacío, aquí es una solución de (print '2', '3', '4' escribe 3 entradas):

class logfile(object): 
    def __init__(self, *args, **kwargs): 
     self.f = file(*args, **kwargs) 
     self.c = False 
    def write(self, logstr): 
     self.c = not self.c 
     if logstr[-1] != '\n': logstr += '\n' 
     if self.c: 
      self.f.write(time.strftime('%D-%T ') + str(logstr)) 

Ésta registra líneas completas (nota: print "4\n", "5" es todavía 2 loglines):

class logfile(object): 
    def __init__(self, *args, **kwargs): 
     self.f = file(*args, **kwargs) 
     self.newline = True 
    def write(self, logstr): 
     if self.newline: 
      self.f.write(time.strftime('%D-%T ')) 
     self.f.write(logstr) 
     self.newline = logstr[-1] == '\n' 

¿Alguien sabe cómo manejar declaraciones de impresión completas en 1 loglines?

1

This article explica su problema. Básicamente, si sys.stdout es una subclase de file, entonces print pasa por alto sys.stdout.write y escribe directamente en sys.stdout.fd.

La solución a su problema es utilizar la composición en lugar de la subclase file.

+1

¿Podría dar un ejemplo? – Hobblin

Cuestiones relacionadas