Pull to refresh

Comments 17

time.sleep(interval)

ага, и тут мы выясняем, что, оказывается, запуск по timer'у (крону) это совершенно не то же самое, что и слип. Крон дает гарантирую запуска в момент времени X (скажем, каждую 5 минуту в 00 секунду), плюс-минус какую-то погрешность. А слип? А слип это ТОТ самый код, который, во-первых, в неудачной реализации жрет 100% cpu, а, во-вторых, не гарантирует ничего. У Вас погрешность запуска будет расти с каждым последующим запуском. И если изначально таймаут для слипа был подобран для 5 минут, то потому Вы внезапно увидите, что задержка запуска составляет 1 час. Я уж не говорю - о всяких приключениях вроде снижения частоты процессора из-за энергосбережения, приколы ntp, или попросту перевод часов... и обо всем этом $&$#*(&$#( приходится думать. С уважением...

Где это вы такой Sleep взяли? В Windows:

void Sleep(
  [in] DWORD dwMilliseconds
);

Спит то количество миллисекунд, которое ей указано, при этом нагружает процессор на 0%, т.к. потоку просто не выделяется процессорное время.

Может в питоне какой то свой слип...

Где это вы такой Sleep взяли?

реализация на уровне ЯП, насколько мне известно, не дает каких-либо гарантий. Да, основные реализации могут не жечь такты cpu, но тут уж как карта ляжет :-)

И всегда стоит задавать дополнительные вопросы "а что если?"

Дело в том, что сам скрипт исполняется какое-то время, допустим 5 секунд, а после этого включается слип на 10 секунд, в итоге получаем периодичность не 10 секунд как хотели а 10+5. Из-за этого таймер должен считаться независимо от исполнения основного скрипта, и тут опять же или вешать потоки/корутины/процессы или просто убрать из скрипта контроль периода и отдать его штатному инструменту автозапуска

Ещё можно просто использовать


while True:
    start_time = time.monotonic()
    {code}
    time.sleep(max(interval - (time.monotonic() - start_time), 0))

. Штатный инструмент автозапуска, это, конечно, хорошо, но, во‐первых, с ним вы каждый раз будете платить за запуск процесса Python, чтение всех модулей, …, во‐вторых, останавливать скрипт выше гораздо удобнее. В варианте выше период должен плавать не так сильно.

Вобщем я понял претензию к слипу, но тут есть 2 стороны. Все зависит от задачи.

Если есть задача выполнять скрипт строго в определенные отметки времени, допустим, запустить процесс бекапа в 03:00 - то да, это лучше делать кроном.

Если задача - запускать какое то действие с паузами в 10 сек, то лучше Sleep (здорового человека, а не который 100% CPU). Время выполнения действия может быть в общем случае неопределено. При использовании крона (или другого средства планирования) может возникнуть ситуация, когда предыдущее действие еще не завершилось, а следующее уже запускается, со всеми вытекающими.

При использовании крона (или другого средства планирования) может возникнуть ситуация, когда предыдущее действие еще не завершилось, а следующее уже запускается, со всеми вытекающими.

эта проблема легко решается. В баш скриптах, например, используется утилита flock. В python - аналогично. Что-то такого плана https://gist.github.com/jirihnidek/430d45c54311661b47fb45a3a7846537

 В баш скриптах, например, используется утилита flock

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

доку читали? Там есть разные варианты поведения - можно ждать освобождения блокировки, а можно падать с ошибкой, если ее не взять (именно второе поведение позволяет не плодить ждущие инстансы). Задается разница буквально одной опцией...

Доку не читал.

 а можно падать с ошибкой, если ее не взять

Звучит как то не очень отказоустойчиво...

ну, обработайте ошибку ) от задачи же зависит.

Тогда мы получим пропуски срабатываний ) это все не годится.

Да, идея автора понятна как тот самый лом и естественно правильна, не нужно переусложнять простые вещи, но действительно реализацию автора можно улучшить. Вы предлагаете использовать крон, а я предложу на системах с systemd использовать таймеры в юнитах. Там у них целый раздел [Timer] есть, где можно настраивать "каждые 2 минуты" или "каждый вторник в 12:00" или другие варианты...

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

Добрый вечер! Да, естественно, если речь идет про crond vs systemd-timer, я при прочих равных выберу последний. В своем же сообщении "крон" я подразумевал как некий принцип некоего планировщика - не важно, будь он на уровне ЯП в виде какой-то подключаемой библиотеки, или как-то еще реализован, но никак не внешний запускатор (хотя и он возможен - при учете, например, контроля за временем выполнения скрипта, чтобы не копились "мертвые" или "зависшие" процессы в системе). То есть в своем сообщении я не имел в виду крон как системный демон. Прошу прощения, если ввел в заблуждение...

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

Реализаций может бесчисленно множество, вплоть до реализации своего мини крона. Но тут вопрос зачем это всё? Где тут усмотрели требования к точности? Или требования к незапуску второго процесса пока не закончился первый? Откуда вообще взялось столько домыслоф о которых автор нигде даже косвенно не упоминал?

Не помню уже откуда: "Делай просто, как можно проще, но не проще, чем нужно"

async, ивент луп и вот это все призваны при написании I/O Bound приложений экономить ресурсы при большой нагрузке

Не совсем так. Асинхронный код всего лишь позволяет не ждать I/O в mainloop, вместо этого продолжая его последовательное (!) выполнение. Нельзя асинхронно производить вычисления - для этого нужна многопоточность. Только с точки зрения I/O - наверное, да, можно сказать про экономию ресурсов. Один асинхронный процесс обработает больше входных данных за период времени из-за отсутствия задержек на ожидание ввода. При этом, большое количество возвратов в mainloop и использование async функций там, где нет непосредственно I/O, создаёт оверхед и увеличивает нагрузку на процессор.

Sign up to leave a comment.

Articles