2012-02-16 19 views
8

yo estaba tratando de crear un atributo personalizado para iniciar la sesión (nombre de la clase de persona que llama, nombre del módulo, etc.) y quedé atrapado con una extraña excepción que me dice que la instancia LogRecord creado en el proceso no tenía los atributos necesarios Después de un poco de las pruebas de que terminé con esto:Python módulo de registro: registradores personalizados

import logging 

class MyLogger(logging.getLoggerClass()): 
    value = None 

logging.setLoggerClass(MyLogger) 

loggers = [ 
    logging.getLogger(), 
    logging.getLogger(""), 
    logging.getLogger("Name") 
] 

for logger in loggers: 
    print(isinstance(logger, MyLogger), hasattr(logger, "value")) 

Esto aparentemente correcta pedazo de rendimientos de código:

False False 
False False 
True True 

falla o función?

Respuesta

5

Mirando el código fuente podemos ver lo siguiente:

root = RootLogger(WARNING) 
def getLogger(name=None): 
    if name: 
     return Logger.manager.getLogger(name) 
    else: 
     return root 

es decir, un registrador de la raíz se crea de forma predeterminada cuando se importa el módulo. Por lo tanto, cada vez que miras para el Looger raíz (pasando un valor falso como la cadena vacía), vas a obtener un objeto logging.RootLogger independientemente de cualquier llamada a logging.setLoggerClass.

En cuanto a la clase de logger siendo utilizados podemos ver:

_loggerClass = None 
def setLoggerClass(klass): 
    ... 
    _loggerClass = klass 

Esto significa que una variable global tiene la clase de logger para ser utilizado en el futuro.

Además de esto, mirando a logging.Manager (utilizado por logging.getLogger), podemos ver esto:

def getLogger(self, name): 
    ... 
      rv = (self.loggerClass or _loggerClass)(name) 

Es decir, si self.loggerClass no está ajustado (que no será menos que haya explícitamente set it), se usa la clase de la variable global.

Por lo tanto, es una característica. El registrador de la raíz es siempre un objeto logging.RootLogger y los otros objetos logger se crean basándose en la configuración en ese momento.

2

logging.getLogger() y logging.getLogger("") no devuelven un MyLogger porque devuelven el registrador raíz de la jerarquía de registro, tal como se describe en el logging documentation:

logging.getLogger ([nombre])

devolver una logger con el nombre especificado o, si no se especifica ningún nombre, devolver un registrador que es el registrador de raíz de la jerarquía.

Por lo tanto, como se ha configurado el registrador de arriba:

>>> logging.getLogger() 
<logging.RootLogger object at 0x7d9450> 
>>> logging.getLogger("foo") 
<test3.MyLogger object at 0x76d9f0> 

No creo que esto está relacionado con la KeyError que comenzó su publicación. Debería publicar el código que provocó que se lanzara esa excepción (test.py).

+0

Gracias por su comentario, he editado la pregunta. pero creo que este comportamiento no es lo que cabría esperar que suceda. – Pastafarianist

+0

¿Por qué no es lo que esperarías que sucediera? Es * precisamente * lo que la documentación dice que sucederá cuando no se especifique ningún nombre. –

+4

Aunque esto es lo que dice la documentación, es contrario a la intuición. Al establecer una clase para los registradores, espero que _todos_loggers tengan esa clase, incluida la raíz y excluyendo las que ya se crearon. – Pastafarianist

Cuestiones relacionadas