Блокировка файла для атомарного доступа не работает - PullRequest
1 голос
/ 30 октября 2019

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

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

Какую ошибку я делаю?

message = sys.argv[1]

lock_file = "test.lock"
_flock = None

def _lock_file():
        _flock = open(lock_file, 'w+')
        while True:
                try:
                        fcntl.flock(_flock, fcntl.LOCK_EX | fcntl.LOCK_NB)
                        break
                except IOError as e:
                        # raise on unrelated IOErrors
                        if e.errno != errno.EAGAIN:
                                raise
                        else:
                                time.sleep(0.1)


def _unlock_file():
        if _flock != None:
                fcntl.flock(_flock, fcntl.LOCK_UN)

_lock_file()
print(message)
time.sleep(30)
_unlock_file()

1 Ответ

1 голос
/ 30 октября 2019

Для меня ниже работает, почему while True?

Используйте lockf вместо flock. Это заботится о приобретении и освобождении замков лучше. Разница в ключах lockf - обязательная блокировка. Это означает, что когда один процесс блокирует раздел файла, ни один другой процесс не может получить доступ к этому разделу файла. flock, с другой стороны, это консультативная блокировка - это означает, что процессы должны решить согласиться на блокировку файла, но ядро ​​не будет применять такую ​​вещь.

import sys
import fcntl
import time

message = sys.argv[1]

lock_file = "test.lock"
_flock = open(lock_file, "w")

def lock_file(f):
        fcntl.lockf(f, fcntl.LOCK_EX)
def unlock_file(f):
        fcntl.lockf(f, fcntl.LOCK_UN)

lock_file(_flock)
print(message)
time.sleep(30)
unlock_file(_flock)
...