¿Cómo puedo registrar la línea actual y astackr información con Python?

Tengo la función de registro de la siguiente manera.

logging.basicConfig( filename = fileName, format = "%(levelname) -10s %(asctime)s %(message)s", level = logging.DEBUG ) def printinfo(string): if DEBUG: logging.info(string) def printerror(string): if DEBUG: logging.error(string) print string 

Necesito iniciar sesión en el número de línea, información de la stack. Por ejemplo:

 1: def hello(): 2: goodbye() 3: 4: def goodbye(): 5: printinfo() ---> Line 5: goodbye()/hello() 

¿Cómo puedo hacer esto con Python?

Resuelto

 def printinfo(string): if DEBUG: frame = inspect.currentframe() stack_trace = traceback.format_stack(frame) logging.debug(stack_trace[:-1]) if LOG: logging.info(string) 

Me da esta información que es exactamente lo que necesito.

 DEBUG 2011-02-23 10:09:13,500 [ ' File "/abc.py", line 553, in \n runUnitTest(COVERAGE, PROFILE)\n', ' File "/abc.py", line 411, in runUnitTest\n printinfo(string)\n'] 

    El nombre de la función actual, el módulo y el número de línea que puede hacer simplemente cambiando la cadena de formato para incluirlos.

     logging.basicConfig( filename = fileName, format = "%(levelname) -10s %(asctime)s %(module)s:%(lineno)s %(funcName)s %(message)s", level = logging.DEBUG ) 

    La mayoría de las personas solo quieren la stack cuando registran una excepción, y el módulo de registro lo hace automáticamente si llama a logging.exception() . Si realmente desea información de la stack en otros momentos, deberá utilizar el módulo de rastreo para extraer la información adicional que necesita.

     import inspect import traceback def method(): frame = inspect.currentframe() stack_trace = traceback.format_stack(frame) print ''.join(stack_trace) 

    Utilice stack_trace [: – 1] para evitar incluir method / printinfo en el seguimiento de la stack.

    A partir de Python 3.2, esto se puede simplificar al pasar el stack_info=True a las llamadas de registro . Sin embargo, deberá usar una de las respuestas anteriores para cualquier versión anterior.

    Respuesta tardía, pero bueno.

    Otra solución es que puede crear su propio formateador con un filtro como se especifica en los documentos aquí . Esta es una característica realmente excelente, ya que ahora ya no tiene que usar una función auxiliar (y tiene que poner la función auxiliar en todos los lugares donde desea que se realice el seguimiento de la stack). En su lugar, un formato personalizado lo implementa directamente en los propios registros.

     import logging class ContextFilter(logging.Filter): def __init__(self, trim_amount) self.trim_amount = trim_amount def filter(self, record): import traceback record.stack = ''.join( str(row) for row in traceback.format_stack()[:-self.trim_amount] ) return True # Now you can create the logger and apply the filter. logger = logging.getLogger(__name__) logger.addFilter(ContextFilter(5)) # And then you can directly implement a stack trace in the formatter. formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s \n %(stack)s') 

    Nota: En el código anterior, recorte los últimos 5 marcos de stack. Esto es solo por conveniencia y para que no mostremos los marcos de stack del propio paquete de registro de Python (también es posible que deba ajustarse para diferentes versiones del paquete de registro).

    Aquí hay un ejemplo que espero te pueda ayudar:

     import inspect import logging logging.basicConfig( format = "%(levelname) -10s %(asctime)s %(message)s", level = logging.DEBUG ) def test(): caller_list = [] frame = inspect.currentframe() this_frame = frame # Save current frame. while frame.f_back: caller_list.append('{0}()'.format(frame.f_code.co_name)) frame = frame.f_back caller_line = this_frame.f_back.f_lineno callers = '/'.join(reversed(caller_list)) logging.info('Line {0} : {1}'.format(caller_line, callers)) def foo(): test() def bar(): foo() bar() 

    Resultado:

     INFO 2011-02-23 17:03:26,426 Line 28 : bar()/foo()/test() 

    Utilice el módulo de rastreo .

     logging.error(traceback.format_exc()) 

    Esto se basa en la respuesta de @mouad pero se vuelve más útil (IMO) al incluir en cada nivel el nombre del archivo (pero no su ruta completa) y el número de línea de la stack de llamadas, y al dejar la stack en la forma más reciente llamada (from) es decir, NO revertido) orden porque así es como quiero leerlo 🙂

    Cada entrada tiene file: line: func () que es la misma secuencia que el stacktrace normal, pero todo en la misma línea es mucho más compacto.

     import inspect def callers(self): caller_list = [] frame = inspect.currentframe() while frame.f_back: caller_list.append('{2}:{1}:{0}()'.format(frame.f_code.co_name,frame.f_lineno,frame.f_code.co_filename.split("\\")[-1])) frame = frame.f_back callers = ' <= '.join(caller_list) return callers 

    Es posible que deba agregar un f_back adicional si tiene alguna llamada intermedia para producir el texto de registro.

      frame = inspect.currentframe().f_back 

    Produce una salida como esta:

     file2.py:620:func1() <= file3.py:211:func2() <= file3.py:201:func3() <= main.py:795:func4() <= file4.py:295:run() <= main.py:881:main() 

    Solo necesito este stacktrace en dos funciones clave, así que agrego la salida de los que llaman al texto en la llamada logger.debug (), como htis:

     logger.debug("\nWIRE: justdoit request -----\n"+callers()+"\n\n") 

    Mira el módulo de rastreo

     >>> import traceback >>> def test(): >>> print "/".join( str(x[2]) for x in traceback.extract_stack() ) >>> def main(): >>> test() >>> main() /launch_new_instance/mainloop/mainloop/interact/push/runsource/runcode//main/test