Запретить создание файла в python - PullRequest
0 голосов
/ 06 апреля 2011

Я работаю на питон-сервере, который одновременно обрабатывает транзакции в нескольких базах данных, каждая из которых хранит данные о производительности для разных приложений.Параллелизм осуществляется с помощью модуля Multiprocessing, поэтому каждый поток транзакций запускается в новом процессе, и схемы защиты данных в совместно используемой памяти нежизнеспособны.Я использую sqlite в качестве моей СУБД, и решил настроить БД каждого приложения в своем собственном файле.К сожалению, это вводит условие гонки при создании БД;Если два процесса попытаются создать БД для одного и того же нового приложения одновременно, оба создадут файл, в котором будет храниться БД.Мои исследования заставляют меня поверить, что невозможно заблокировать файл до его создания;Есть ли какой-то другой механизм, который я могу использовать, чтобы гарантировать, что файл не создается, а затем записывается одновременно?

Заранее спасибо, Дэвид

Ответы [ 5 ]

1 голос
/ 06 апреля 2011

Обычный способ Unix-стиля справиться с этим для обычных файлов - просто попытаться создать файл и посмотреть, не сработает ли он.В случае с Python это будет:

try:
    os.open(filename, os.O_WRONLY | os.O_CREAT | os.O_EXCL)
except IOError: # or OSError?
    # Someone else created it already.

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

0 голосов
/ 06 апреля 2011

Вы можете использовать флаги POSIX O_EXCL и O_CREAT для open(2), чтобы гарантировать, что только один процесс получит файл и, следовательно, базу данных;O_EXCL не будет работать через NFSv2 или более раннюю версию, и было бы довольно шатко полагаться на него для других сетевых файловых систем.

Библиотека liblockfile реализует сетевую файловую системумеханизм безопасной блокировки описан в справочной странице open(2), что было бы удобно;но я вижу только готовые привязки Ruby и Perl.В зависимости от ваших потребностей, возможно, было бы полезно предоставить привязки Python, или, возможно, просто заново реализовать алгоритм:

   O_EXCL Ensure that this call creates the file: if this flag is
          specified in conjunction with O_CREAT, and pathname
          already exists, then open() will fail.  The behavior of
          O_EXCL is undefined if O_CREAT is not specified.

          When these two flags are specified, symbolic links are not
          followed: if pathname is a symbolic link, then open()
          fails regardless of where the symbolic link points to.

          O_EXCL is only supported on NFS when using NFSv3 or later
          on kernel 2.6 or later.  In environments where NFS O_EXCL
          support is not provided, programs that rely on it for
          performing locking tasks will contain a race condition.
          Portable programs that want to perform atomic file locking
          using a lockfile, and need to avoid reliance on NFS
          support for O_EXCL, can create a unique file on the same
          file system (e.g., incorporating hostname and PID), and
          use link(2) to make a link to the lockfile.  If link(2)
          returns 0, the lock is successful.  Otherwise, use stat(2)
          on the unique file to check if its link count has
          increased to 2, in which case the lock is also successful.
0 голосов
/ 06 апреля 2011

Вы не упомянули платформу, но в linux open() или os.open() в python принимает параметр flags, который вы можете использовать. Флаг O_CREAT создает файл, если он не существует, а флаг O_EXCL выдает ошибку, если файл уже существует. Вам также понадобятся O_RDONLY, O_WRONLY или O_RDWR для указания режима доступа. Вы можете найти эти константы в модуле os.

Например: fd = os.open(filename, os.O_RDWR | os.O_CREAT | os.O_EXCL)

0 голосов
/ 06 апреля 2011

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

0 голосов
/ 06 апреля 2011

Назовите файлы базы данных таким образом, чтобы они гарантированно не конфликтовали.

http://docs.python.org/library/tempfile.html

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