Давайте поговорим немного про логгирование в Python.
Да, меня это ДЕЙСТВИТЕЛЬНО беспокоит, и я хочу об этом поговорить ;-)
Совсем недавно столкнулся с тем, что достаточно серьезный проект при портировании с Linux на MacOS потерял логгирование. Ну нет лог файла - и все тут. Полез в код разбираться - выяснилось, что разработчики очень любили изобретать велосипеды и делали логгирование через файл, открытый ручками и обычную запись туда переменных - прямо в файл. Все это работало... до поры до времени. Пришлось на скору руку переписывать.
В общем, мораль сей басни такова...
Есть в Python СТАНДАРТНЫЙ модуль logging - его и нужно использовать для разного типа логгирования. Батарейка-то уже включена ;-)
Чтобы пример кода не был совсем тривиальным - приведу решение для той ситуации, когда у нас есть несколько многопроцессных РАЗНЫХ демонов на Twisted на одной машине, а еще и cron-скрипт запускается время от времени. И всю жизнедеятельность этого дурдома нужно логгировать в один файл
import os
import logging
from twisted.python import log
CURRENT_PATH = os.path.realpath(os.path.dirname(__file__))
# Все это "по уму" обычно запихивается в нормальный конфиг-файл
LOG_DIR = os.path.join(CURRENT_PATH, 'logs')
LOG_FILE = os.path.join(LOG_DIR, 'super-puper.log')
LOG_LEVEL = logging.INFO
# инициализируем
FORMAT = ('%(asctime)-15s %(levelname)s %(message)s')
if not os.path.exists(LOG_DIR):
os.mkdir(LOG_DIR)
logging.basicConfig(format=FORMAT, filename=LOG_FILE, handler=logging.handlers.RotatingFileHandler)
observer = log.PythonLoggingObserver(loggerName='twisted')
observer.start()
observer.logger.setLevel(LOG_LEVEL)
# класс-примесь для логгирования - в принципе - необязательно, реализация может быть разная - хоть функциями
class BasicLogClass():
def _log(self, msg):
log.msg(msg, logLevel=logging.INFO)
def _error(self, msg):
log.msg(msg, logLevel=logging.ERROR)
def _warning(self, msg):
log.msg(msg, logLevel=logging.WARNING)
В данном варианте работоспособность не проверял, но логика применения именно такая - выкусил из работающего проекта.
Кстати, если у кроновских скриптов нет использования twisted'овского reactor, то могуть быть проблемы, нужно подумать. Как вариант - использовать развилку в инициализации и логгировании без применения observer, но не уверен.