Как я могу регистрировать текущую строку и информацию о стеке с помощью Python?
У меня есть функция регистрации следующим образом.
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
Мне нужно ввести номер строки, информацию о стеке. Например:
1: def hello():
2: goodbye()
3:
4: def goodbye():
5: printinfo()
---> Line 5: goodbye()/hello()
Как я могу сделать это с помощью Python?
решаемые
def printinfo(string):
if DEBUG:
frame = inspect.currentframe()
stack_trace = traceback.format_stack(frame)
logging.debug(stack_trace[:-1])
if LOG:
logging.info(string)
дает мне эту информацию, которая именно то, что мне нужно.
DEBUG 2011-02-23 10:09:13,500 [
' File "/abc.py", line 553, in <module>\n runUnitTest(COVERAGE, PROFILE)\n',
' File "/abc.py", line 411, in runUnitTest\n printinfo(string)\n']
Ответы
Ответ 1
Текущее имя функции, модуль и номер строки, которую вы можете сделать, просто изменив строку формата, чтобы включить их.
logging.basicConfig(
filename = fileName,
format = "%(levelname) -10s %(asctime)s %(module)s:%(lineno)s %(funcName)s %(message)s",
level = logging.DEBUG
)
Большинство людей хотят только стек при регистрации исключения, а модуль журнала делает это автоматически, если вы вызываете logging.exception()
. Если вам действительно нужна информация о стеке в другое время, вам нужно будет использовать модуль трассировки для извлечения дополнительной информации, которая вам нужна.
Ответ 2
import inspect
import traceback
def method():
frame = inspect.currentframe()
stack_trace = traceback.format_stack(frame)
print ''.join(stack_trace)
Используйте stack_trace [: - 1], чтобы избежать включения метода /printinfo в трассировку стека.
Ответ 3
Как и в случае с Python 3.2, это можно упростить, передав флаг stack_info=True
в протоколирование вызовов. Однако для любой более ранней версии вам понадобится один из вышеперечисленных ответов.
Ответ 4
Поздний ответ, но хорошо.
Другое решение состоит в том, что вы можете создать свой собственный форматировщик с фильтром, как указано в документах здесь. Это действительно замечательная функция, так как теперь вам больше не нужно использовать вспомогательную функцию (и вам нужно помещать вспомогательную функцию везде, где вы хотите трассировку стека). Вместо этого пользовательский отформатированный реализует его непосредственно в самих журналах.
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')
Примечание. В приведенном выше коде я обрезаю последние 5 кадров стека. Это просто для удобства и чтобы мы не отображали фреймы стека из самого пакета протоколов python (его также можно было бы скорректировать для разных версий пакета регистрации)
Ответ 5
Вот пример, который я надеюсь, что он может вам помочь:
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()
Результат:
INFO 2011-02-23 17:03:26,426 Line 28 : bar()/foo()/test()
Ответ 6
Используйте модуль traceback.
logging.error(traceback.format_exc())
Ответ 7
Посмотрите на модуль трассировки
>>> import traceback
>>> def test():
>>> print "/".join( str(x[2]) for x in traceback.extract_stack() )
>>> def main():
>>> test()
>>> main()
<module>/launch_new_instance/mainloop/mainloop/interact/push/runsource/runcode/<module>/main/test