У меня есть вопрос, очень похожий на этот вопрос, где мне нужно соблюдать следующие условия:
- Если файл открыт для чтения, этот файл может быть только открыть для чтения любым другим процессом / программой
- Если файл открыт для записи, этот файл может быть открыт только для чтения любым другим процессом / программой
Решение опубликовано в связанном вопросе используется сторонняя библиотека, которая добавляет произвольный файл .LOCK
в тот же каталог, что и рассматриваемый файл. Это решение, которое работает только в отношении программы, в которой используется эта библиотека, и не препятствует использованию файла другими процессами / программами, поскольку они могут быть не реализованы для проверки связи .LOCK
.
В сущности, я sh должен скопировать этот результат, используя только стандартную библиотеку Python.
BLUF : Нужен спецификация реализации стандартной библиотеки c до Windows для исключительной блокировки файлов
Чтобы привести пример решения проблемы, предположим, что на файле имеется:
- 1 общая сеть / диск
- 2 пользователя в отдельных процессах / программах
Предположим, что пользователь 1 запускает программу A для файла и в какой-то момент выполняется следующее:
with open(fp, 'rb') as f:
while True:
chunk = f.read(10)
if chunk:
# do something with chunk
else:
break
Таким образом, они перебирают файл по 10 байт за раз.
Теперь пользователь 2 запускает программу B для того же файла через мгновение:
with open(fp, 'wb') as f:
for b in data: # some byte array
f.write(b)
При Windows рассматриваемый файл немедленно усекается, и программа A прекращает итерацию (даже если она не было сделано) и программа B начинает запись в файл. Поэтому мне нужен способ гарантировать, что файл не может быть открыт в другом режиме, который изменил бы его содержимое при открытии ранее.
Я искал библиотеку msvcrt , а именно msvcrt.locking()
интерфейс. Что мне удалось сделать, так это убедиться, что файл, открытый для чтения, может быть заблокирован для чтения, но никто другой не может прочитать файл (так как я блокирую весь файл):
>>> f1 = open(fp, 'rb')
>>> f2 = open(fp, 'rb')
>>> msvcrt.locking(f1.fileno(), msvcrt.LK_LOCK, os.stat(fp).st_size)
>>> next(f1)
b"\x00\x05'\n"
>>> next(f2)
PermissionError: [Errno 13] Permission denied
Это приемлемо Результат, просто не самый желанный.
В том же сценарии Пользователь 1 запускает Программу А, которая включает в себя:
with open(fp, 'rb') as f
msvcrt.locking(f.fileno(), msvcrt.LK_LOCK, os.stat(fp).st_size)
# repeat while block
msvcrt.locking(f.fileno(), msvcrt.LK_UNLCK, os.stat(fp).st_size)
Затем Пользователь 2 запускает Программу В мгновение спустя, происходит тот же результат, и файл усекается.
На этом этапе мне бы хотелось, чтобы пользователь 2 выдал ошибку, в которой говорится, что файл открыт для чтения в другом месте и не может быть записан в данный момент. Но если пользователь 3 приедет и откроет файл для чтения, проблем не будет.
Обновление:
Потенциальное решение - изменить разрешения для file (за исключением перехвата, если файл уже используется):
>>> os.chmod(fp, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
>>> with open(fp, 'wb') as f:
# do something
PermissionError: [Errno 13] Permission denied <fp>
Это не самое лучшее решение (особенно если у пользователей не было разрешения даже изменять разрешения). Все еще ищите правильное решение для блокировки, но msvcrt
не препятствует усечению и записи, если файл заблокирован для чтения. По-видимому, до сих пор не существует способа создания эксклюзивной блокировки с помощью стандартной библиотеки Python.