LINUX.ORG.RU

Удаление lockfile при завершении программы python (аналог trap в bash?)

 ,


0

4

TL;DR: Как правильно по-питонячьи реализовать аналог trap или что-то, что будет делать тоже самое для запуска функции при завершении программы вне зависимости от результата, в т. ч. при ошибке?

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

Вопрос: как по-питонячьи этот lockfile удалять при завершении программы вне зависимости от причины завершения (удача/неудача) с учетом того, что программа работает как сервис, т. е. один запуск предполагает длительной взаимодействие с разными файлами - интерактивная программа?

try...except...finallу в скрипте обертке запуска программы? Какой-то хитрый декоратор или хук? Желательно решить это средствами стандартной библиотеки. Поясните для newbie.



Последнее исправление: curbar (всего исправлений: 3)

try…except…final

Это не спасет вас от kill -9. Мне кажется, вам понадобится дополнительная информация о процессе записанная в файл, как минимум pid. Тогда на этапе запуска скрипта вы проверяете, что процесс создавший лок-файл еще существует. Дополнительно можно накрутить еще какие-нибудь таймауты, идентификаторы сессии - на что фантазии хватит.

FishHook
()

Ты неправильно это делаешь.

Само наличие файла не должно означать, что процесс запущен, тебе нужно залочить файл через flock(2) или fcntl. Лок автоматически удалится, когда будет закрыт последний fd с этим локом, что случится в том числе если твоя прога сдохнет.

Для пистона нагуглилась библиотечка (https://py-filelock.readthedocs.io/en/latest/), но это всё можно легко сделать руками.

hateyoufeel ★★★★★
()

Можно переделать проверку с наличия файла на проверку блокировки файла, например как рассказывают здесь https://stackforgeeks.com/blog/ensure-a-single-instance-of-an-application-in-linux Блокировка спадает при завершении процесса. Это делает ядро. Поэтому некорректное завершение программы не является проблемой с точки зрения механизма блокировки повторного запуска. Единственно что валяющиеся после завершения программы временные файлы это некрасиво. Да и в целом локфайл не особо надёжный механизм, т.к. файл можно тупо удалить во время работы программы и запустить ещё один или сколько нужно экземпляров

cobold ★★★★★
()
Ответ на: комментарий от firkax

Опередил.

но это всё можно легко сделать руками.

Не просто можно но и нужно. Тащить библиотеку ради двух строк open+flock это верх глупости.

Там не только open+flock, но и аналог на венде.

hateyoufeel ★★★★★
()
Ответ на: комментарий от hateyoufeel

@cobold

Понял, я объяснил мою проблему с учетом решения, которое я вижу, и с некоторыми упрощениями. Поэтому, возможно, ваши варианты могут не подойти.

Моя программа - сервис на flask, который принимает файлы csv на вход, обрабатывает данные из файлов с помощью pandas, потом сравнивает с имеющимися на сервере данными из такого же csv файла, при определенных обстоятельствах делает расчеты и перезаписывает csv файл на сервере. То есть обработки одновременно двух csv файлов, которые загружаются через интерфейс загрузки файла, не должно происходить, т. к. это может сломать csv файл на сервере или произвести неверные расчеты с одним из входящих csv файлов.

Исходя из этих деталей, подойдет ли этот flock?

curbar
() автор топика
Ответ на: комментарий от curbar

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

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от FishHook

Лок с файла удалится. Сам файл может и остаться, это не имеет значения. Сходи сам прочитай ссылку, которую ты притащил, лалка! Там именно это и написано.

hateyoufeel ★★★★★
()
Последнее исправление: hateyoufeel (всего исправлений: 1)
Ответ на: комментарий от curbar

@cobold

Понял, я объяснил мою проблему с учетом решения, которое я вижу, и с некоторыми упрощениями. Поэтому, возможно, ваши варианты могут не подойти.

Моя программа - сервис на flask, который принимает файлы csv на вход, обрабатывает данные из файлов с помощью pandas, потом сравнивает с имеющимися на сервере данными из такого же csv файла, при определенных обстоятельствах делает расчеты и перезаписывает csv файл на сервере. То есть обработки одновременно двух csv файлов, которые загружаются через интерфейс загрузки файла, не должно происходить, т. к. это может сломать csv файл на сервере или произвести неверные расчеты с одним из входящих csv файлов.

Исходя из этих деталей, подойдет ли этот flock?

А может тебе, ну это, взять базу данных и не мучиться? Но по минимуму, ты можешь просто лочить свой csv на сервере через flock и снимать лок после обработки запроса. Отдельного файла тут не нужно.

hateyoufeel ★★★★★
()
Последнее исправление: hateyoufeel (всего исправлений: 1)
Ответ на: комментарий от hateyoufeel

Сам файл может и остаться, это не имеет значения.

Имеет. Файл должен остаться т.к. мы не хотим зря дёргать запись на диск бесполезными действиями. Диск вообще может быть в read-only.

firkax ★★★★★
()
Ответ на: комментарий от firkax

Сам файл может и остаться, это не имеет значения.

Имеет. Файл должен остаться т.к. мы не хотим зря дёргать запись на диск бесполезными действиями. Диск вообще может быть в read-only.

На какой диск, дядя? Все чоткие посоны создают свои локфайлы в /run/user/$UID давно уже.

Только ТСу это не нужно, у него уже есть csv на сервере, который можно лочить.

hateyoufeel ★★★★★
()
Последнее исправление: hateyoufeel (всего исправлений: 2)

trap в баше для обработчиков ЮНИКС сигналов, а не для очистки ресурсов. В общем случае нужен другой процесс, который будет мониторить твой и очищать файлы. Возможно, в systemd есть что-то для этого. Альтернативно - переделать программу так, чтобы глобальный локфайл был не нужен.

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

Во-первых, с какой стати на сервере что-то «поломается», если все операции атомарные? Во-вторых, зачем нужен флок, когда просто смотрим, есть уже файл в обработке, и если есть, то отказываем клиенту с сервис бизи.

seiken ★★★★★
()
Ответ на: комментарий от curbar

Может тогда посмотреть в сторону uwsgi spooler https://smirnov-am.github.io/background-jobs-with-flask/ ? Если конечно в проекте используется uwsgi. Идея в том чтобы при поступлении файла на обработку добавлять в очередь задачу, а обрабатывать задачи единственным воркером, т.е. последовательно. Таким образом параллельного доступа к файлу не будет.

Ну и ещё есть вариант с https://uwsgi-docs.readthedocs.io/en/latest/PythonDecorators.html#uwsgidecorators.lock

cobold ★★★★★
()
Последнее исправление: cobold (всего исправлений: 1)
Ответ на: комментарий от FishHook

Это не спасет вас от kill -9

бгг, хот тейк от растомана. Открою страшную тайну, от SIGKILL и trap в баше не спасет. И вообще ничего не спасет, да и не должно спасать, потому что этот сигнал не перехватывается.

Lrrr ★★★★★
()
Последнее исправление: Lrrr (всего исправлений: 1)
Ответ на: комментарий от solmut

нужно проверять запущен ли процесс, НО не факт, что под тем же PID, тот же самый процесс с вероятностью один на миллион

rtxtxtrx
()
Последнее исправление: rtxtxtrx (всего исправлений: 1)

создай файл, открой его дескриптор и удали. Как только дескриптор закроется - удалится и лос. А вообще стандарт пистон библиотеки для работы с локами такое умеют

ivanich10
()
Последнее исправление: ivanich10 (всего исправлений: 1)

как-то неправильно всё...попытка решения задачи управления ящиком изнутри ящика ;-)

есть пресловутый systemd. Вот он мониторит «жив/нет/упал/отжался». И подчищает ошмётки после падений.

PS/ кстати, почему у вас запуск второго экземпляра приводит к ошибкам а не к ускорению разборов или повышению надёжности? вот тут корень бед..

MKuznetsov ★★★★★
()
Последнее исправление: MKuznetsov (всего исправлений: 1)
Ответ на: комментарий от cumvillain

Куча интерактивного софта использует локфайлы

это - их проблема :-)

поймите верно: лок файл это костыль. Надо по максимуму избегать «вставания на костыли», избавится от них будет сложно. Кроме того уровень сверху (систем-д или что-там у ТС, мега-конвеер) всё равно придётся информировать о наличии костылей, их назначении и в какую свалку сваливать старые.

далее, задачи типа

«Программа работает с файлами, в т. ч. принимает файлы на загрузку, их обрабатывает, сохраняет и прочее» как у топик-стартера,

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

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

MKuznetsov ★★★★★
()
Ответ на: комментарий от cumvillain

Примитивы синхронизаци — костыль.

конечно костыль.

к тому их надо ещё правильно (без гонок)готовить, соблюсти системные или проектные требования (куда класть, как бесконфликтно именовать, что содержат), сообщать о них другим уровням.

и всё равно это не даст «гарантированно удалить лок-файл из программы». Программа может убиться по сегфолту или вообще по питанию. А лок останется.

MKuznetsov ★★★★★
()
Последнее исправление: MKuznetsov (всего исправлений: 1)
Ответ на: комментарий от cumvillain

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

один маленький лок может вызвать массу гемороя. И тащит в программу за собой пачку системных тех.требований. Совершенно внезапно делает программу (скрипт на грёбанном питоне) прибитой к конкретной ОС.

ЭТО КОСТЫЛЬ.

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

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

файловая система,это файловая система. Она может отвалится,заглючить вся, или по частям. Она может быть сетевой, вся или опять-же частями.

Как это относится к чему? Если ты создаешь локфайл, ты создаешь его в /run, где нет сетевой файловой системы. Если ты лочишь существующий файл (Maildir какой-нибудь), то он нужен чтобы твоя программа работать могла. И если все разваливается, то твоя программа выходит с ошибкой.

На разных ОС может вести себя по разному.

Иии? У тебя open() на разных ОС может вести себя по разному.

один маленький лок может вызвать массу гемороя. И тащит в программу за собой пачку системных тех.требований. Совершенно внезапно делает программу (скрипт на грёбанном питоне) прибитой к конкретной ОС.

Нет, не делает.

ЭТО КОСТЫЛЬ.

Нет, не костыль.

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

Ты ничего не знаешь про дизайн, лол.

cumvillain
()
Ответ на: комментарий от cumvillain

Если ты создаешь локфайл, ты создаешь его в /run, где нет сетевой файловой системы

всё бросаешь и идёшь искать /run например в виндовс, архитектор ты наш, прошаренный в дизайне :-)

А потом пишешь объяснительную боссу, почему скрипт питона перекладывающий файлы из inbox в outbox получился системно-зависимым и предъявляет требования о наличии и специфики /run.

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

всё бросаешь и идёшь искать /run например в виндовс, архитектор ты наш, прошаренный в дизайне :-)

Тебе рассказать про библиотеки для кросс-платформенной разработки или сам справишься?

А потом пишешь объяснительную боссу

Ахаха что.

cumvillain
()