Возможно, у меня есть долго работающая программа, которая в настоящее время имеет 4 процесса, но может быть настроена на большее.Я исследовал протоколирование из нескольких процессов с использованием Python's logging
и использую подход SocketHandler, обсуждаемый здесь .У меня никогда не было проблем с одним логгером (без сокетов), но из того, что я прочитал, мне сказали, что он в конечном итоге потерпит неудачу.Насколько я понимаю, неизвестно, что произойдет, если вы попытаетесь записать в один и тот же файл одновременно.Мой код по существу выполняет следующее:
import logging
log = logging.getLogger(__name__)
def monitor(...):
# Spawn child processes with os.fork()
# os.wait() and act accordingly
def main():
log_server_pid = os.fork()
if log_server_pid == 0:
# Create a LogRecordSocketServer (daemon)
...
sys.exit(0)
# Add SocketHandler to root logger
...
monitor(<configuration stuff>)
if __name__ == "__main__":
main()
Итак, мои вопросы: Нужно ли создавать новый log
объект после каждого os.fork()
?Что происходит с существующим глобальным log
объектом?
Делая вещи такими, какие я есть, могу ли я обойти проблему, которую пытаюсь избежать (несколько открытых файлов / сокетов)?Будет ли это терпеть неудачу и почему это потерпит неудачу (я хотел бы иметь возможность определить, не удастся ли в будущем подобным реализациям)?
Кроме того, каким образом выполняется метод "normal" (one log=
expression)входа в один файл из нескольких процессов не удается?Это вызывает IOError / OSError?Или это просто не полностью записывает данные в файл?
Если бы кто-то мог предоставить ответ или ссылки, чтобы выручить меня, это было бы здорово.Спасибо.
FYI : я тестирую на Mac OS X Lion, и код, вероятно, будет работать на CentOS 6 VM на компьютере с Windows (если это имеет значение).Какое бы решение я не использовал, оно не должно работать в Windows, но должно работать в системе на основе Unix.
ОБНОВЛЕНИЕ: Этот вопрос начал отходить от ведения журнала конкретного поведения и больше касаетсясфера действия linux с файловыми дескрипторами во время форков.Я вытащил один из моих учебников для колледжа, и кажется, что если вы откроете файл в режиме добавления из двух процессов (не перед разветвлением), они оба смогут правильно записать в файл, если ваша запись не превышаетфактический буфер ядра (хотя может потребоваться использовать строковую буферизацию, но в этом еще нет уверенности).Это создает 2 записи таблицы файлов и одну запись таблицы v-узла.Открытие файла с последующим разветвлением не должно работать, но, похоже, до тех пор, пока вы не превысите буфер ядра, как раньше (я делал это в предыдущей программе).
Так что я думаю, если вы хотите независимую от платформы многопроцессорную регистрацию, вы используете сокеты и создаете новый SocketHandler после каждой развилки, чтобы быть безопасными, как предложил Vinay ниже (это должно работать везде).Для меня, так как у меня есть строгий контроль над тем, на какой ОС запускается мое программное обеспечение, я думаю, что я собираюсь использовать один глобальный log
объект с FileHandler (открывается в режиме добавления по умолчанию и буферизуется в большинстве ОС),Документация для open
гласит: «Отрицательная буферизация означает использование системного значения по умолчанию, которое обычно является линейной буферизацией для tty-устройств и полностью буферизовано для других файлов. Если не указано, используется системное значение по умолчанию».или я мог бы просто создать свой собственный поток регистрации, чтобы быть уверенным в буферизации строк.И чтобы быть ясным, я в порядке:
# Process A
a_file.write("A\n")
a_file.write("A\n")
# Process B
a_file.write("B\n")
производит ...
A\n
B\n
A\n
, пока это не производит ...
AB\n
\n
A\n
Vinay (или кто-либо еще), насколько я не прав?Дай мне знать.Спасибо за дополнительную ясность / уверенность, которую вы можете предоставить.