Усеченные файлы журнала вывода при ведении журнала stdout и stderr отдельно - PullRequest
2 голосов
/ 27 сентября 2019

Я настроил команду подпроцесса в менеджере контекста, которая направляет stdout и stderr в отдельные файлы через мой собственный регистратор.Это вариант ответа, приведенного здесь: https://stackoverflow.com/a/4838875/4844311

Мой код выглядит следующим образом:

import logging
import subprocess

with StreamLogger(logging.DEBUG, my_out_logger) as out:
    with StreamLogger(logging.ERROR, my_err_logger) as err:
        p = subprocess.Popen(cmd, shell=False, stdout=out, stderr=err)
        p.communicate()
        p.wait()

, где my_out_logger и my_err_logger - это записи объектов с дескрипторами, которые регистрируются вфайлы и т. д.

Код StreamLogger аналогичен коду, указанному по ссылке выше:

import io
import os
import threading
import select
import time

class StreamLogger(io.IOBase):
    def __init__(self, level, logger):
        self.logger = logger
        self.level = level
        self.pipe = os.pipe()
        self.thread = threading.Thread(target=self._flusher)
        self.thread.start()

    def _flusher(self):
        self._run = True
        buf = b''
        while self._run:
            for fh in select.select([self.pipe[0]], [], [], 0)[0]:
                buf += os.read(fh, 1024)
                while b'\n' in buf:
                    data, buf = buf.split(b'\n', 1)
                    self.write(data.decode())
            time.sleep(0.01)
        self._run = None

    def write(self, data):
        return self.logger.log(self.level, data)

    def fileno(self):
        return self.pipe[1]

    def close(self):
        if self._run:
            self._run = False
            while self._run is not None:
                time.sleep(0.01)
            os.close(self.pipe[0])
            os.close(self.pipe[1])

Единственное существенное отличие между моим кодом и кодом, предоставленным ответом по ссылке вышев том, что мой код отправляет сообщение регистрации в регистратор, который перенаправляет в соответствии с его дескрипторами, а не напрямую, как в коде по ссылке.

Этот код в большинстве случаев работает нормально.

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

Я не уверен, почему это происходит или где исправить код.Сейчас я только что добавил оператор time.sleep(0.3) между p.communicate() и p.wait(), и это уменьшило частоту усеченных файлов, но это выглядит как уродливое решение.

Я бы лучше понял, что происходит не таки исправить это правильно.Я приветствую любые предложения или идеи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...