Закрыть ... [X]

Как сделать цикл функции с

Можно range(n) использовать, чтобы повторить что-то n раз в Питоне:

for _ in range(60): do_something() time.sleep(1)

"Правильный" и "эффективный" ли это способ? Это зависит от конкретной задачи.

Код прост и понятен: вызвать do_something() функцию 60 раз, каждый следующий вызов происходит не ранее чем через секунду после завершения предыдущего вызова. В конце ждём секунду прежде чем завершить цикл.

Представьте do_something() требует полсекунды в среднем, тогда цикл займёт полторы минуты или больше. Хорошо ли это—зависит от задачи.

Если вы хотите, чтобы вызовы происходили бы на границе каждой секунды:

for _ in range(60): do_something() time.sleep(1 - time.time() % 1)

C точностью до активности других процессов, потоков (особенностей планировщиков процессов/потоков в операционной системе, особенностей GIL реализации выбранной версии Питон-интерпретатора), каждый вызов do_something() кроме первого происходит близко ко времени, когда time.time() целые значения возвращает.

К примеру, если time.time() вернёт X.3 секунд, то time.sleep() будет спать не менее 0.7 секунд (если обработчик сигналов исключение не выбросит) и значит следующий вызов do_something() произойдёт в X + 1 секунд по системному времени (если оно сильно не прыгнуло пока мы спали). В этом случае вызовы do_something() могут быть более равномерно распределены и цикл завершится почти ровно через минуту согласно time.time() (если время выполнения do_something() менее секунды). Хорошо ли это—зависит от задачи.

Если вы не хотите запускать do_something(), если больше минуты прошло согласно выбранному таймеру, можно явное условие использовать:

deadline = time.monotonic() + 60 while time.monotonic() < deadline: do_something() time.sleep(1)

Вещи, которые необходимо принять во внимание в зависимости от задачи:

  • Какое желаемое поведение, если do_something() может выполняться больше секунды: пропустить итерацию, запустить в отдельном потоке, пуле потоков/процессов?
  • Какое желаемое поведение, если системное время прыгнет (потому что кто-то закрыл крышку ноутбука во время цикла или hibernation системы по любой другой причине произошло или мобильная OS отгрузила ваш процесс, чтобы энергию сэкономить через какое-то время, или код внутри VM—большие прыжки возможны). Хотите ли вы продолжить выполнение цикла как как сделать цикл функции с будто ничего не произошло, когда система проснётся, или отменить последующие вызовы (устарели), или выполнить оставшиеся вызовы как можно быстрее, без паузы или вообще все сразу (deadline прошёл)?

К примеру, если время изменится во время выполнения print_some_times() из @ReinRaus ответа, то что по вашему произойдёт? Гарантированно ли это поведение документацией sched модуля (не изменится ли оно между разными реализациями/версиями Питона)? Важно ли это в вашем конкретном случае? (думаю, ясность простого цикла со sleep() может стать особенно привлекательной в этот момент).

В качестве вариации на тему, можно периодически вызывать функцию в фоновом потоке или использовать возможности различных циклов событий. В более сложных случаях, если у вас нет особых предпочтений, можно использовать apscheduler модуль, чтобы встроить планировщик в ваше приложение. В каких-то случаях имеет смысл воспользоваться планировщиком системы (для больших интервалов) таких как cron и Windows Task Scheduler.

Полезно знать причины, по которым call_repeatedly() функцию убрали из PEP 3156 -- Asynchronous IO Support Rebooted: the "asyncio" Module:

Note: A previous version of сделать this PEP defined a method named call_repeatedly(), which promised to call a callback at regular intervals. This has been withdrawn because the design of such a function is overspecified. On the one hand, a simple timer loop can easily be emulated using a callback that reschedules itself using call_later() ; it is also easy to write coroutine containing a loop and a sleep() call (a toplevel function in the module, see below). On the other hand, due to the complexities of accurate timekeeping there are many traps and pitfalls here for the unaware (see PEP 418), and different use cases require different behavior in edge cases. It is impossible to offer an API for this purpose that is bullet-proof in all cases, so it is deemed better to let application designers decide for themselves what kind of timer loop to implement.


Источник: https://ru.stackoverflow.com/questions/577284/%D0%9A%D0%B0%D0%BA-%D0%BF%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D1%8C%D0%BD%D0%BE-%D1%81%D0%B4%D0%B5%D0%BB%D0%B0%D1%82%D1%8C-%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9-%D1%86%D0%B8%D0%BA%D0%BB


Поделись с друзьями



Рекомендуем посмотреть ещё:



Python - Как правильно сделать временный цикл? Нужен помощник по уходу

Как сделать цикл функции с Как сделать цикл функции с Как сделать цикл функции с Как сделать цикл функции с Как сделать цикл функции с Как сделать цикл функции с Как сделать цикл функции с Как сделать цикл функции с Как сделать цикл функции с

ШОКИРУЮЩИЕ НОВОСТИ