Python / Linux: как определить, когда перемещенный файл полностью доступен? - PullRequest
0 голосов
/ 04 августа 2020

У меня есть папка, в которую постоянно добавляются новые файлы. У меня есть сценарий python, который использует os.listdir () для поиска этих файлов, а затем автоматически выполняет их анализ. Однако файлы довольно большие, поэтому кажется, что они появляются в os.listdir () еще до того, как были полностью записаны / скопированы. Есть ли способ отличить guish, какие файлы не находятся в процессе перемещения? Сравнение размеров с помощью os.path.getsize (), похоже, не работает.

Raspbian Buster на Pi4 с Python 3.7.3. Я новичок в программировании и linux.

Спасибо!

Ответы [ 2 ]

1 голос
/ 04 августа 2020

В программировании это называется concurrency , когда вычисления происходят одновременно, и порядок выполнения не гарантируется. В вашем случае одна программа начинает читать файл до того, как другая программа закончит запись в него. Эта конкретная проблема называется проблемой читателя-писателя и на самом деле довольно часто встречается во встроенных системах.

Есть несколько решений этой проблемы, но самым простым и распространенным является замок . Простейший вид блокировки защищает ресурс от одновременного доступа более чем одной программой. Фактически, он гарантирует, что операции с ресурсом происходят атомарно . Блокировка реализуется как объект, который может быть получен или освобожден (обычно это функции объекта). Программа пытается получить блокировку в al oop, которая повторяется до тех пор, пока программа не получит блокировку. Когда блокировка получена, она предоставляет программе, в которой она находится, возможность выполнить некоторый блок кода (обычно это простой оператор if), после чего блокировка снимается. Обратите внимание, что то, что я называю программой, обычно называется поток .

В Python вы можете использовать объект threading.Lock. Сначала вам нужно создать объект Lock.

from threading import Lock
file_lock = Lock()

Затем в каждом потоке подождите, чтобы получить блокировку, прежде чем продолжить. Если вы установите blocking=True, это приведет к тому, что весь поток прекратит работу до тех пор, пока не будет получена блокировка, без необходимости al oop.

file_lock.acquire(blocking=True):
# atomic operation
file_lock.release()

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

1 голос
/ 04 августа 2020

Для концептуального объяснения перемещений Atomi c и перекрестных файловых систем см. Этот перемещает Python (действительно может сэкономить ваше время)

Вы можете использовать следующие подходы к решить вашу проблему: -

-> Мониторинг событий файловой системы с помощью Pyinotify использование Pynotify

-> Заблокируйте файл на несколько секунд, используя flock

-> Используя lsof, мы можем в основном проверить процессы, которые используют конкретный файл.

`from subprocess import check_output,Popen, PIPE
try:
   lsout=Popen(['lsof',filename],stdout=PIPE, shell=False)
   check_output(["grep",filename], stdin=lsout.stdout, shell=False)
except:
   #check_output will throw an exception here if it won't find any process using that file`

просто напишите код обработки журнала в части except, и все будет хорошо на go.

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

- > Вы можете проверить файл, который используется другим процессом, перебрав PID / s в / pro c для определенного c id (при условии, что у вас есть контроль над программой, которая постоянно добавляет новые файлы. для идентификации его идентификатора). * 1 026 *

-> Можно проверить, есть ли в файле дескриптор с помощью psutil.

...