Python - как проверить, используется ли файл другим приложением?

Я хочу открыть файл, который периодически записывается другим приложением. Это приложение не может быть изменено. Поэтому я хотел бы открывать файл только тогда, когда я знаю, что он не был записан другим приложением.

Есть ли питонический способ сделать это? В противном случае, как мне добиться этого в Unix и Windows?

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

Я хотел бы начать с этого вопроса. На данный момент неважно, не имеет значения чтение / запись этих других приложений.

Я понимаю, что это, вероятно, зависит от ОС, поэтому сейчас это может не быть связано с Python.


person Gilad Naor    schedule 26.02.2009    source источник
comment
вы пытаетесь добиться ротации журналов ??   -  person vladr    schedule 26.02.2009
comment
Не совсем так, но не слишком далеко. Я хочу создать приложение поверх существующего.   -  person Gilad Naor    schedule 26.02.2009


Ответы (3)


Будет ли ваш скрипт python открывать файл для записи или чтения? Устаревшее приложение открывает и закрывает файл между операциями записи или оставляет его открытым?

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

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


ОБНОВЛЕНИЕ

Хорошо, зная (из вашего комментария), что:

устаревшее приложение открывает и закрывает файл каждые X минут, но я не хочу предполагать, что в t = t_0 + n * X + eps он уже закрыл файл.

затем меняются параметры задачи. Фактически это может быть сделано независимо от ОС с учетом нескольких предположений или в виде комбинации методов, зависящих от ОС и независимых от ОС. :)

  1. OS-independent way: if it is safe to assume that the legacy application keeps the file open for at most some known quantity of time, say T seconds (e.g. opens the file, performs one write, then closes the file), and re-opens it more or less every X seconds, where X is larger than 2*T.
    • stat the file
    • вычесть время модификации файла из now(), получив D
    • если T ‹= DX то откройте файл и сделайте с ним что хотите
    • Это может быть достаточно безопасно для вашего приложения. Безопасность повышается по мере уменьшения _11 _ / _ 12_. В * nix вам, возможно, придется дважды проверить /etc/ntpd.conf правильность настройки временного шага по сравнению с настройкой нарастания (см. Tinker). Для Windows см. MSDN.
  2. Windows: in addition (or in-lieu) of the OS-independent method above, you may attempt to use either:
    • sharing (locking): this assumes that the legacy program also opens the file in shared mode (usually the default in Windows apps); moreover, if your application acquires the lock just as the legacy application is attempting the same (race condition), the legacy application will fail.
      • this is extremely intrusive and error prone. Unless both the new application and the legacy application need synchronized access for writing to the same file and you are willing to handle the possibility of the legacy application being denied opening of the file, do not use this method.
    • attempting to find out what files are open in the legacy application, using the same techniques as ProcessExplorer (the equivalent of *nix's lsof)
      • you are even more vulnerable to race conditions than the OS-independent technique
  3. Linux/etc.: in addition (or in-lieu) of the OS-independent method above, you may attempt to use the same technique as lsof or, on some systems, simply check which file the symbolic link /proc/<pid>/fd/<fdes> points to
    • you are even more vulnerable to race conditions than the OS-independent technique
    • очень маловероятно, что устаревшее приложение использует блокировку, но если это так, блокировка не является реальным вариантом, если устаревшее приложение не может корректно обрабатывать заблокированный файл (путем блокировки, а не путем сбоя - и если ваше собственное приложение может гарантировать, что файл не будет оставаться заблокированным, блокируя устаревшее приложение на период времени.)

ОБНОВЛЕНИЕ 2

Если вы предпочитаете «проверить, открыт ли файл в устаревшем приложении» (навязчивый подход, склонный к состояниям гонки), вы можете решить указанное состояние гонки следующим образом:

  1. проверка того, открыт ли файл в устаревшем приложении (а-ля lsof или ProcessExplorer)
  2. приостановка устаревшего процесса приложения
  3. повторение проверки на шаге 1, чтобы подтвердить, что устаревшее приложение не открыло файл между шагами 1 и 2; задержите и перезапустите с шага 1, если это так, в противном случае перейдите к шагу 4
  4. ведение бизнеса с файлом - в идеале просто переименование его для последующей независимой обработки, чтобы приостановить работу устаревшего приложения на минимальное время
  5. возобновление устаревшего процесса приложения
person vladr    schedule 26.02.2009
comment
Устаревшее приложение открывает и закрывает файл каждые X минут, но я не хочу предполагать, что в t = t_0 + n * X + eps оно уже закрыло файл. - person Gilad Naor; 26.02.2009

Unix не имеет блокировки файлов по умолчанию. Лучшее, что я могу предложить для среды Unix, - это посмотреть исходники команды lsof. Он имеет глубокие знания о том, какие файлы открываются в процессе. Вы можете использовать это как основу своего решения. Вот исходные коды Ubuntu для lsof.

person Peter Rowell    schedule 26.02.2009
comment
Похоже, это хорошее решение для Unix. Я могу просто проанализировать вывод lsof для нужного мне файла, прежде чем обращаться к нему. Не совсем безопасно без замка, но справиться с корректностью могу только в 99,99% случаев. Мне просто нужно решение для Windows. - person Gilad Naor; 26.02.2009

Одна вещь, которую я сделал, - это временно переименовал файл в python. Если мы можем переименовать его, значит, никакой другой процесс его не использует. Я тестировал это только на Windows.

person Jim Carroll    schedule 26.02.2009