Что произойдет, если я войду в один файл из нескольких разных процессов в python?

Я потратил несколько часов, чтобы разобраться в этом, сначала о тех вопросах:

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

И из небольшого теста:

#!/bin/env python
import os
import logging

logger = logging.getLogger('spam_application')
logger.setLevel(logging.DEBUG)
# create file handler which logs even debug messages
fh = logging.FileHandler('spam.log')
logger.addHandler(fh)
formatter = logging.Formatter(
    '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)

for i in xrange(10000):
    p = os.getpid()
    logger.debug('Log line number %s in %s', i, p)

И я запустил его с помощью

./test.py & ./test.py & ./test.py & ./test.py &

Я обнаружил, что в spam.log нет ничего плохого. Такое поведение может поддержать вывод выше.

Но проблемы, возникающие:

  • Что это означает здесь?
  • А каковы сценарии использования этого, только для вращения файла?

Наконец, если два процесса выполняют запись в одном файле, я имею в виду, что они вызывают запись (2) в том же файле, которые уверены, что данные из двух процессов не чередуются (ядро или файловая система?) и как. [ПРИМЕЧАНИЕ: я просто хочу видеть в глубине сценария syscall, любой удар по этому поводу приветствуется.]

EDIT1:

Сделайте этот и этот просто существует для совместимости между различными средами os, такими как windows, linux или mac?

EDIT2:

Еще один тест, подавайте строки 8 КБ в logging.debug каждый раз. И на этот раз я вижу поведение "чередования" в spam.log. Это поведение просто указано в PIPE_BUF на одной странице выше. Таким образом, кажется, что поведение понятно на linux, использование O_APPEND в порядке, если размер записи (2) меньше, чем PIPE_BUF.

+3
источник поделиться
3 ответа

Я копал все глубже и глубже. Теперь я думаю об этом ясно:

  • С O_APPEND параллельная запись (2) из ​​нескольких процессов в порядке. Это просто порядок строк не определен, но строки не чередуются и не переписываются. И размер данных на любую сумму, согласно Niall Douglas, отвечает за Понимание одновременной записи файлов из нескольких процессов. Я протестировал об этом "на любую сумму" на linux и не нашел верхний предел, поэтому я предполагаю, что это правильно.

  • Без O_APPEND это будет беспорядок. Вот что говорит POSIX: "В этом томе POSIX.1-2008 не указывается поведение одновременной записи в файл из нескольких процессов. Приложения должны использовать некоторую форму элемента управления concurrency.

  • Теперь мы входим в python. Тест, который я сделал в EDIT3, это 8K, я нашел его источником. Python write() использует fwrite (3), и мой питон устанавливает здесь BUFF_SIZE, который равен 8192. Согласно ответу от abarnert в Размер буфера по умолчанию для файла в Linux. Этот 8192 имеет долгую историю.

Однако, дополнительная информация приветствуется.

+2
источник

Я бы не стал полагаться на тесты здесь. Странные вещи могут произойти только в условиях гонки, а показание состояния гонки по критерию почти не имеет смысла, поскольку состояние гонки вряд ли произойдет. Таким образом, он может хорошо работать для 1000 тестовых прогонов и случайным образом ломаться позже в prod... На странице, которую вы цитируете, говорится:

запись в один файл из нескольких процессов не поддерживается, потому что нет стандартного способа сериализации доступа к одному файлу через несколько процессов в Python

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

Если вы действительно хотите убедиться в этом, вам придется погрузиться в исходный код Python (для вашей версии), чтобы контролировать, как фактически выполняется ведение журнала, и контролировать, безопасно ли это в вашей файловой системе. И вам всегда будет угрожать возможность того, что последующая оптимизация в модуле регистрации нарушит ваши предположения.

IMHO, что является причиной предупреждения в журнале регистрации журналов, а также наличие специального модуля для параллельного ведения журнала в том же файле. Этот последний не полагается на что-то неопределенное, но просто использует явное блокирование.

+1
источник
другие ответы

Связанные вопросы


Похожие вопросы

Я пробовал подобный код, как это (я пробовал в Python 3)

import threading
for i in range(0,100000):
     t1 = threading.Thread(target= funtion_to_call_logger, args=(i,))
     t1.start()

Для меня это работало совершенно нормально, аналогичная проблема решена здесь.

Это заняло много времени процессора, но не памяти.

РЕДАКТИРОВАТЬ:
Штраф означает, что все запрошенные вещи были зарегистрированы, но Порядок отсутствовал. Состояние Гонки Гонки все еще не исправлено,

0
источник

Посмотрите другие вопросы по меткам или Задайте вопрос