Как записать имя исходного файла и номер строки в Python

123

Можно ли украсить / расширить стандартную систему ведения журнала Python, чтобы при вызове метода ведения журнала он также регистрировал файл и номер строки, в которой он был вызван, или, возможно, метод, который его вызвал?

digy
источник

Ответы:

228

Конечно, проверьте средства форматирования в документации журнала. В частности, переменные leno и pathname.

% (pathname) s Полный путь к исходному файлу, в котором был выполнен вызов журнала (если доступен).

% (filename) s Часть пути к имени файла.

% (module) s Module (часть имени в имени файла).

% (funcName) s Имя функции, содержащей вызов регистрации.

% (lneno) d Номер исходной строки, в которой был выполнен вызов регистрации (если доступно).

Выглядит примерно так:

formatter = logging.Formatter('[%(asctime)s] p%(process)s {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s','%m-%d %H:%M:%S')
Себ
источник
1
И, да, необходимо учитывать беспорядок в верхнем и нижнем регистрах в переменных.
Том Пол
1
Иначе называется «очень плохо реализованный случай верблюда».
Джон Спенсер,
81

Помимо очень полезного ответа Себа , вот удобный фрагмент кода, который демонстрирует использование регистратора в разумном формате:

#!/usr/bin/env python
import logging

logging.basicConfig(format='%(asctime)s,%(msecs)d %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s',
    datefmt='%Y-%m-%d:%H:%M:%S',
    level=logging.DEBUG)

logger = logging.getLogger(__name__)
logger.debug("This is a debug log")
logger.info("This is an info log")
logger.critical("This is critical")
logger.error("An error occurred")

Создает этот вывод:

2017-06-06:17:07:02,158 DEBUG    [log.py:11] This is a debug log
2017-06-06:17:07:02,158 INFO     [log.py:12] This is an info log
2017-06-06:17:07:02,158 CRITICAL [log.py:13] This is critical
2017-06-06:17:07:02,158 ERROR    [log.py:14] An error occurred
codeforester
источник
5
Используйте это для получения дополнительных сведений: formatter = logging.Formatter ('% (asctime) s,% (levelname) -8s [% (filename) s:% (module) s:% (funcName) s:% (lineo) d]) % (message) s ')
Гириш Гупта
есть ли способ изменить только в одном месте в верхней части кода независимо от того, печатаются ли сообщения журнала? Я бы хотел два режима, один с большим количеством распечаток, чтобы увидеть, что именно делает программа; и один, когда он достаточно стабилен, когда вывод не отображается.
Мари. П.
3
@ Marie.P. не задавайте разные вопросы в комментариях. Ответ - это уровни регистрации.
bugmenot123
4

Чтобы развить вышеизложенное таким образом, чтобы журнал отладки отправлялся стандартным образом:

import logging
import sys

root = logging.getLogger()
root.setLevel(logging.DEBUG)

ch = logging.StreamHandler(sys.stdout)
ch.setLevel(logging.DEBUG)
FORMAT = "[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s"
formatter = logging.Formatter(FORMAT)
ch.setFormatter(formatter)
root.addHandler(ch)

logging.debug("I am sent to standard out.")

Помещение вышеуказанного в файл с именем debug_logging_example.pyдает результат:

[debug_logging_example.py:14 -             <module>() ] I am sent to standard out.

Затем, если вы хотите отключить логирование, комментируйте root.setLevel(logging.DEBUG).

Для отдельных файлов (например, назначения классов) я нашел, что это гораздо лучший способ сделать это, чем использование print()операторов. Где это позволяет вам отключить вывод отладки в одном месте перед отправкой.

orangepips
источник
1

Для разработчиков, использующих PyCharm или Eclipse pydev, следующее создаст ссылку на источник оператора журнала в выходных данных журнала консоли:

import logging, sys, os
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG, format='%(message)s | \'%(name)s:%(lineno)s\'')
log = logging.getLogger(os.path.basename(__file__))


log.debug("hello logging linked to source")

См. Гиперссылки на исходный файл Pydev в консоли Eclipse для более подробного обсуждения и истории.

символы
источник
0
# your imports above ...


logging.basicConfig(
    format='%(asctime)s,%(msecs)d %(levelname)-8s [%(pathname)s:%(lineno)d in 
    function %(funcName)s] %(message)s',
    datefmt='%Y-%m-%d:%H:%M:%S',
    level=logging.DEBUG
)

logger = logging.getLogger(__name__)

# your classes and methods below ...
# An naive Sample of usage:
try:
    logger.info('Sample of info log')
    # your code here
except Exception as e:
    logger.error(e)

В отличие от других ответов, это будет регистрировать полный путь к файлу и имя функции, которая могла вызвать ошибку. Это полезно, если у вас есть проект с более чем одним модулем и несколькими файлами с одинаковыми именами, распределенными в этих модулях.

Хосана Гомеш
источник