Сбой Python при использовании статического класса
Я делаю свои первые шаги в Python и дошел до того, что мне нужен модуль журналирования. Причины, по которым я не выбрал обработчик вращающихся файлов:
- Я хотел, чтобы при каждом запуске кода создавалась новая папка с новыми файлами журналов.
- Использование обычных имен файлов (
myName_X.log
и не по умолчаниюmyName.log.X
). - Ограничьте файлы журнала числом строк, а не размером файла (как это делается с помощью обработчика вращающихся файлов).
Я написал такой модуль, используя встроенный в Python модуль логирования, но у меня есть две проблемы:
- Новая папка и файл будут созданы, а данные регистрации будут напечатаны в файле. Однако когда
main()
запускается во второй раз (см. код ниже), вновь созданный файл заблокирован и не может быть удален из проводника, пока я не закрою IDE или не сниму блокировку через Process Explorer. - Интерпретатор IPython зависает при втором запуске
main()
, Если я попробуюpdb
модуль, он также зависает.
Я использую WinPython 3.3.5 (с Spyder 2.3.0beta). Я часами пытался найти решение этой проблемы. Я не знаю, является ли это проблемой в моем коде или скорее ошибкой в Spyder.
Общие замечания по кодированию всегда приветствуются.
main_example.py:
import myLogging
def main():
try:
myLoggerInstance = myLogging.MyLogger()
# Do stuff...
# logging example
for i in range(0, 3):
msg = 'Jose Halapeno on a stick {0}'.format(i)
myLoggerInstance.WriteLog('DEBUG', msg)
print('end of prints...')
finally:
myLoggerInstance._closeFileHandler()
print('closed file handle...')
if __name__ == "__main__":
main()
myLogging.py:
import logging
import time
import os
class MyLogger:
_linesCounter = 0
_nNumOfLinesPerFile = 100000
_fileCounter = 0
_dirnameBase = os.path.dirname(os.path.abspath(__file__))
_dirname = ''
_filenameBase = 'logfile_{0}.log'
_logger = logging.getLogger('innerGnnLogger')
_severityDict = {'CRITICAL' : logging.CRITICAL, 'ERROR': logging.ERROR, 'WARNING':
logging.WARNING, 'INFO': logging.INFO, 'DEBUG': logging.DEBUG}
@staticmethod
def __init__():
# remove file handle
MyLogger._closeFileHandler()
# create folder for session
MyLogger._dirname = MyLogger._dirnameBase + time.strftime("\\logs_%Y_%m_%d-
%H_%M_%S\\")
MyLogger._dirname = MyLogger._dirname.replace('\\\\', '/')
if not os.path.exists(MyLogger._dirname):
os.makedirs(MyLogger._dirname)
# set logger
MyLogger._logger.setLevel(logging.DEBUG)
# create console handler and set level to debug
MyLogger._hConsole = logging.StreamHandler()
MyLogger._hFile = logging.FileHandler(MyLogger._dirname + \
MyLogger._filenameBase.format(MyLogger._fileCounter))
MyLogger._hConsole.setLevel(logging.WARNING)
MyLogger._hFile.setLevel(logging.DEBUG)
# create formatter
MyLogger._formatter = logging.Formatter('%(asctime)s %(filename)s, %(funcName)s, %(lineno)s, %(levelname)s: %(message)s')
# add formatter to handlers
MyLogger._hConsole.setFormatter(MyLogger._formatter)
MyLogger._hFile.setFormatter(MyLogger._formatter)
# add handlers to logger
MyLogger._logger.addHandler(MyLogger._hConsole)
MyLogger._logger.addHandler(MyLogger._hFile)
@staticmethod
def _StartNewFileHandler():
MyLogger._closeFileHandler()
# create new file handler
++MyLogger._fileCounter
MyLogger._hFile = logging.FileHandler(MyLogger._dirname + \
MyLogger._filenameBase.format(MyLogger._fileCounter))
MyLogger._hFile.setLevel(logging.DEBUG)
MyLogger._hFile.setFormatter(MyLogger._formatter)
MyLogger._logger.addHandler(MyLogger._hFile)
@staticmethod
def WriteLog(severity, message):
if (len(MyLogger._logger.handlers) < 2):
MyLogger._StartNewFileHandler()
MyLogger._linesCounter += 1
MyLogger._logger.log(MyLogger._severityDict[severity], message)
if (MyLogger._linesCounter >= MyLogger._nNumOfLinesPerFile):
MyLogger._logger.info('Last line in file')
MyLogger._StartNewFileHandler()
MyLogger._linesCounter = 0
@staticmethod
def _closeFileHandler():
if (len(MyLogger._logger.handlers) > 1):
MyLogger._logger.info('Last line in file')
MyLogger._logger.handlers[1].stream.close()
MyLogger._logger.removeHandler(MyLogger._logger.handlers[1])