Подтвердить что ты не робот

Python не освобождает дескрипторы файлов для файла журнала

У меня есть приложение, которое должно запускать ряд прогонов моделирования. Я хочу настроить механизм ведения журнала, где все logrecords регистрируются в файле general.log, и все журналы для запуска симуляции идут в run00001.log,.... Для этого я определил класс Run. в __init__() для runlog добавляется новый дескриптор файла.

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

Я установил некоторые процедуры, чтобы проверить это следующим образом

основная процедура

import Model
try:
    myrun = Model.Run('20130315150340_run_49295')
    ha = raw_input('enter')
    myrun.log.info("some info")
except:
    traceback.print_exc(file=sys.stdout)

ha = raw_input('enter3')

Класс Run определен в модуле Model следующим образом

import logging
class Run(object):

    """ Implements the functionality of a single run. """
    def __init__(self, runid):
        self.logdir="."
        self.runid          = runid
        self.logFile        = os.path.join(self.logdir , self.runid + '.log')
        self.log            = logging.getLogger('Run'+self.runid)
        myformatter         = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
        myhandler      = logging.FileHandler(self.logFile)
        myhandler.setLevel(logging.INFO)
        myhandler.setFormatter(myformatter)
        self.log.addHandler(myhandler) 

Затем я использую проводник процесса программы, чтобы следить за файловыми обработчиками. И я вижу, что бегуны появляются, но никогда не исчезают.

Есть ли способ заставить это?

4b9b3361

Ответ 1

Вам нужно вызвать .close() в обработчике файлов.

Когда ваш класс Run завершается, вызовите:

handlers = self.log.handlers[:]
for handler in handlers:
    handler.close()
    self.log.removeHandler(handler)

Ответ 2

Вы также можете полностью отключить ведение журнала. В этом случае файловые дескрипторы освобождаются:

logging.shutdown()

Это закроет открытые дескрипторы всех настроенных обработчиков регистрации.

Мне нужно было иметь возможность удалить файл журнала после завершения модульного теста, и я смог удалить его сразу после вызова метода logging.shutdown().

Ответ 3

Я использовал интерактивную среду Python (Spyder). По-видимому, Spyder использует ведение журнала внутри. Таким образом, logging.shutdown() не дает желаемого эффекта. Следующее выполнение этой же программы удвоило записи журнала, 3-е выполнение утроило их и т.д. Обработчики, по-видимому, не удаляются с помощью shutdown() в этой среде. Кроме того, я никоим образом не нарушил Spyder, выполнив явный вызов shutdown(). Непонятные.

Код Martijn для явного закрытия и удаления обработчиков, по одному, работал в среде Spyder.