Pull to refresh

Надежные бесконечные циклы в Python

Reading time2 min
Views9.1K
В питоновском блоге разгорелась дискуссия об оформлении бесконечных циклов, что эстетичнее: while True или while 1<5 :-) Этот топик — мой опыт и рассуждения на тему бесконечных циклов и их реализации в питоне. Звиняйте, что не могу опубликовать в питоновском блоге — поэтому пишу здесь.

На мой взгляд работа с такими циклами зиждется на двух китах:
Кит 1: Они не существуют. Да-да, бесконечный цикл — своего рода чеширский кот, который может незаметно для программиста раствориться, оставив улыбку. И вот чтобы от вашей программы и результатов ее работы тоже не оставалась одна улыбка (а скорее недовольная гримасса начальника/заказчика), приходится соблюдать определенную осторожность. Каждый бесконечный цикл когда-то начался, а значит, когда-нибудь закончится, самое главное, чтобы он закончился когда удобно вам, а не поставщику данных, пользователю, тыкнувшему Ctrl+C, или прилетевшему НЛО. Проектируйте точки выхода из цикла. Чаще всего это будет конец итерации, впрочем возможен выход из середины. А иногда будут такие случаи, что перед выходом, кровь из носу, надо сделать какие-то действия, может даже еще одну-две итерации. Значит: выход из цикла надо крепко держать в своих руках и не отдавать на откуп сторонним библиотекам.

Кит 2: Долой магию. Под «магией» я понимаю использование нестандартных «мего-крутых» гиковских вещей, поведение которых вы не можете прогнозировать на все 100%. Я сам люблю написать несколько строчек, чтобы все сразу сделалось как надо. Вопрос в том, всегда ли при изменении начальных условий эта мега-крутости будут вести себя устойчиво и предсказуемо? Если вы еще не изучили их досконально, то может надежнее и эффективнее использовать более классические подходы? А то получится, что сэкономили 10 строчек, получили массу гемора и падений в критические моменты, и в конце-концов, чтобы от них избавиться дописали еще 50 строк кода :)
Как вы уже поняли, «магия» — понятие относительное. Когда я только начинал изучать питон, мне и конструкция вида
url=self._url + (http_params and (glue + '&'.join(['%s=%s' % (k,v) for k,v in http_params.items()])) or '')
казалась магией.

На основе этого я выработал свой подход создания бесконечных циклов. Заводится вспомогательная переменная, назвать можно как угодно, я обычно называю working, далее все просто:
working = True
while working:
    …
А дальше когда надо меняем working = False, цикл докручивается до конца, а следующий не начинается. Впрочем подход гибкий — можно не просто выйти из цикла, а сделать еще какие-то действия, выйти по середине (if not working: break) или даже прокрутить еще один-два цикла — все как требуется по задаче.
Причем совершенно необязательно менять эту переменную в самом цикле. Можно повесить обработчик на сигналы ОС и по определенному сигналу сбросить этот флаг. Так можно сделать красивый выход из цикла, чтобы при нажатии Ctrl+C на экран не вываливался трейсбек, и все наработанные данные валились вместе с ним в тартарары. Так есть возможность довести работу до логической точки, сохранить файлы, записать все изменения в БД и красиво выйти, помахав пользователю ручкой.
Такой подход зарекомендовал себя как гибкий и надежный, и активно используется в разных демонах.
Какие подходы используете вы?
Это мой первый хабратопик — пожелания и комментарии приветствуются

Tags:
Hubs:
Total votes 2: ↑1 and ↓10
Comments4

Articles