Python: заблокировать файл - PullRequest
3 голосов
/ 30 января 2011

У меня есть приложение Python, работающее в Linux. Он вызывается каждую минуту от cron. Он проверяет каталог на наличие файлов и, если он находит, обрабатывает его - это может занять несколько минут. Я не хочу, чтобы следующее задание cron забирало файл, обрабатываемый в данный момент, поэтому я блокирую его, используя приведенный ниже код, который вызывает portalocker. Проблема в том, что это не работает. Следующему заданию cron удается получить дескриптор файла, возвращенный для файла, все готово к обработке.

def open_and_lock(full_filename):
    file_handle = open(full_filename, 'r')
    try:
        portalocker.lock(file_handle, portalocker.LOCK_EX
                            | portalocker.LOCK_NB)
        return file_handle
    except IOError:
        sys.exit(-1)

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

UPDATE

Благодаря @Winston Ewert я проверил код и обнаружил, что дескриптор файла закрывался до завершения обработки. Похоже, что теперь он работает, за исключением блоков второго процесса в portalocker.lock, а не выдает исключение.

Ответы [ 5 ]

6 голосов
/ 30 января 2011

Вы используете флаг LOCK_NB, который означает, что вызов неблокируемый и сразу же вернется в случае сбоя.Это предположительно происходит во втором процессе.Причина, по которой он все еще может прочитать файл, заключается в том, что portalocker в конечном итоге использует блокировки flock (2) и, как упоминалось в справочной странице flock (2) :

flock (2) устанавливает только консультативные блокировки;при наличии подходящих разрешений для файла процесс может свободно игнорировать использование flock (2) и выполнять операции ввода / вывода для файла.

Чтобы исправить это, вы можете использовать fcntl.Функция flock напрямую (portalocker - это просто оболочка в Linux) и проверяет возвращаемое значение, чтобы убедиться, что блокировка прошла успешно.

4 голосов
/ 19 июня 2015

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

import fcntl

def acquireLock():
    ''' acquire exclusive lock file access '''
    locked_file_descriptor = open('lockfile.LOCK', 'w+')
    fcntl.lockf(locked_file_descriptor, fcntl.LOCK_EX)
    return locked_file_descriptor

def releaseLock(locked_file_descriptor):
    ''' release exclusive lock file access '''
    locked_file_descriptor.close()

lock_fd = acquireLock()

# ... do stuff with exclusive access to your file(s)

releaseLock(lock_fd)
2 голосов
/ 30 января 2011

Не используйте cron для этого. Linux имеет inotify , которая может уведомлять приложения, когда происходит событие файловой системы. Существует привязка Python для inotify, называемая pyinotify .

Таким образом, вам не нужно блокировать файл - вам просто нужно реагировать на IN_CLOSE_WRITE события (т.е. когда файл, открытый для записи, был закрыт). (Вам также не нужно порождать новый процесс каждую минуту.)

Альтернативой использованию pyinotify является incron , который позволяет вам написать incrontab (очень в том же стиле, что и crontab) для взаимодействия с системой inotify.

1 голос
/ 30 января 2011

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

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

0 голосов
/ 30 января 2011

Я думаю fcntl.lockf - это то, что вы ищете.

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