formato de cadena de registro de Python

Estoy usando el formateador de registros de python para formatear registros y tengo un valor fmt de

fmt = "[%(filename)s:%(lineno)s] %(message)s" 

Lo que me gustaría es que “[file.py:20]” se extienda a 10 caracteres de ancho (por ejemplo). Si fuera un valor que hubiera sido fácil, pero ¿hay alguna manera de estirar toda esta estructura a una longitud específica? Quiero algo como:

 tmp = "[%(filename)s:%(lineno)s]" fmt = "%(tmp)10s %(message)s" 

Me gustaría saber si esto es posible utilizando el formato de cadena o si puedo engañar al formateador de python de alguna manera para obtener lo que quiero.

Opción 1

Comience aquí: http://docs.python.org/library/logging.html#formatter-objects

Creará su propia subclase personalizada de Formatter que proporciona su propio método de format único.

Luego, debe asegurarse de llamar a setFormatter() en cada uno de sus Handlers para que usen su nuevo formateador.

opcion 2

Crea tu propia subclase de LogRecord con la propiedad adicional.

Subclase Logger y anule makeRecord para crear su nueva subclase de LogRecord .

Proporcione un formato personalizado que use este nuevo valor de propiedad.

Como ejemplo, este formateador garantiza un ancho fijo "[%(filename)s:%(lineno)s]" al truncar el nombre de archivo o al relleno a la derecha (después del número de línea) con espacios.

 class MyFormatter(logging.Formatter): width = 10 def format(self, record): max_filename_width = self.width - 3 - len(str(record.lineno)) filename = record.filename if len(record.filename) > max_filename_width: filename = record.filename[:max_filename_width] a = "%s:%s" % (filename, record.lineno) return "[%s] %s" % (a.ljust(self.width), record.msg) if __name__ == '__main__': logger = logging.getLogger('simple_example') logger.setLevel(logging.DEBUG) ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) formatter = MyFormatter() ch.setFormatter(formatter) logger.addHandler(ch) logger.debug('No one expects the spammish repetition') 

EDITAR:

Si desea garantizar un ancho mínimo de 10 caracteres, elimine las cosas del nombre del archivo.

 def format(self, record): a = "%s:%s" % (record.filename, record.lineno) return "[%s] %s" % (a.ljust(self.width), record.msg) 

Usando la respuesta de @ rob-cowie como base, he encontrado lo siguiente útil:

 class MyFormatter(logging.Formatter): width = 24 datefmt='%Y-%m-%d %H:%M:%S' def format(self, record): cpath = '%s:%s:%s' % (record.module, record.funcName, record.lineno) cpath = cpath[-self.width:].ljust(self.width) record.message = record.getMessage() s = "%-7s %s %s : %s" % (record.levelname, self.formatTime(record, self.datefmt), cpath, record.getMessage()) if record.exc_info: # Cache the traceback text to avoid converting it multiple times # (it's constant anyway) if not record.exc_text: record.exc_text = self.formatException(record.exc_info) if record.exc_text: if s[-1:] != "\n": s = s + "\n" s = s + record.exc_text #if record.stack_info: # if s[-1:] != "\n": # s = s + "\n" # s = s + self.formatStack(record.stack_info) return s logFormatter = MyFormatter() logger = logging.getLogger("example") logger.setFormatter(logFormatter) 

Lo que da salida como:

 WARNING 2014-03-28 16:05:09 module:function:31 : Message WARNING 2014-03-28 16:05:09 dule:longerfunctions:140 : Message