Добрый день!
Хочу поинтересоваться, как будет правильно составить конструкцию на питоне, которая должна выполняться, пока результатом выполнения функции является ошибка? Думаю, что реализуется с помощью try except, а как именно — не знаю…
- python
задан 29 окт 2012 в 10:47
xenollxenoll
4112 золотых знака7 серебряных знаков20 бронзовых знаков
1 ответ
def foo():
#smth
raise Exception('Exception')
def main():
while True:
try:
foo()
except:
print 'expected exception'
else:
#break loop
break
main()
ответ дан 29 окт 2012 в 10:53
modenmoden
8926 серебряных знаков16 бронзовых знаков
Decorator is a good approach.
from functools import wraps
import time
class retry:
def __init__(self, success=lambda r:True, times=3, delay=1, raiseexception=True, echo=True):
self.success = success
self.times = times
self.raiseexception = raiseexception
self.echo = echo
self.delay = delay
def retry(fun, *args, success=lambda r:True, times=3, delay=1, raiseexception=True, echo=True, **kwargs):
ex = Exception(f"{fun} failed.")
r = None
for i in range(times):
if i > 0:
time.sleep(delay*2**(i-1))
try:
r = fun(*args, **kwargs)
s = success(r)
except Exception as e:
s = False
ex = e
# raise e
if not s:
continue
return r
else:
if echo:
print(f"{fun} failed.", "args:", args, kwargs, "\nresult: %s"%r)
if raiseexception:
raise ex
def __call__(self, fun):
@wraps(fun)
def wraper(*args, retry=0, **kwargs):
retry = retry if retry>0 else self.times
return self.__class__.retry(fun, *args,
success=self.success,
times=retry,
delay=self.delay,
raiseexception = self.raiseexception,
echo = self.echo,
**kwargs)
return wraper
some usage examples:
@retry(success=lambda x:x>3, times=4, delay=0.1)
def rf1(x=[]):
x.append(1)
print(x)
return len(x)
> rf1()
[1]
[1, 1]
[1, 1, 1]
[1, 1, 1, 1]
4
@retry(success=lambda x:x>3, times=4, delay=0.1)
def rf2(l=[], v=1):
l.append(v)
print(l)
assert len(l)>4
return len(l)
> rf2(v=2, retry=10) #overwite times=4
[2]
[2, 2]
[2, 2, 2]
[2, 2, 2, 2]
[2, 2, 2, 2, 2]
5
> retry.retry(lambda a,b:a+b, 1, 2, times=2)
3
> retry.retry(lambda a,b:a+b, 1, "2", times=2)
TypeError: unsupported operand type(s) for +: 'int' and 'str'
Как продолжать цикл, пока ошибка не исчезнет?
Мне нужно, что бы код выглядел не вот так:
try:
ticker_value_at_start_date = TickerValue.objects.get(date=date, ticker=ticker)
except TickerValue.DoesNotExist:
try:
date = date - timedelta(1)
ticker_value_at_start_date = TickerValue.objects.get(date=date, ticker=ticker)
except TickerValue.DoesNotExist:
try:
date = date - timedelta(2)
ticker_value_at_start_date = TickerValue.objects.get(date=date, ticker=ticker)
except:
date = date - timedelta(3)
ticker_value_at_start_date = TickerValue.objects.get(date=date, ticker=ticker)
а вот так :
count = 1
While not TickerValue.DoesNotExist:
date = date - timedelta(count)
ticker_value_at_start_date = TickerValue.objects.get(date=date, ticker=ticker)
Как реализовать такой цикл?)
-
Вопрос задан
-
105 просмотров
Используй try-else для отслеживания успешного завершения вызова и break для выхода из цикла.
for d in range(0, 10): # сколько отступов делать
try:
#к слову, так у тебя date будет считаться не -1, -2, -3... а -1, -3, -6...
date = date - timedelta(d)
pass # операция, которую ты хочешь выполнить
except TickerValue.DoesNotExist: #отработает при ошибке
pass #или time.sleep(), чтобы подождать перед следующим вызовом - если надо
else: #отработает при успешном выполнении блока try
break #выходим из for
Пригласить эксперта
-
Показать ещё
Загружается…
21 сент. 2023, в 19:28
10000 руб./за проект
21 сент. 2023, в 19:06
11111 руб./за проект
21 сент. 2023, в 19:00
6000000 руб./за проект
Минуточку внимания
You can use continue in Python try-except but ‘continue‘ is allowed within an ‘except‘ or ‘finally‘ only if the try block is in a loop. ‘continue‘ will cause the next iteration of the loop to start.
A simple example code tries putting two or more functions in a list and using a loop to call your function.
def f():
print('Function f')
def g():
print('Function g')
funcs = [f, g]
for func in funcs:
try:
func()
except:
continue
Output:
How to continue for loop after exception?
Answer: After the first for-loop, add the try/except
. Then if an error is raised, it will continue with the next file.
for infile in listing:
try:
if infile.startswith("ABC"):
fo = open(infile,"r")
for line in fo:
if line.startswith("REVIEW"):
print infile
fo.close()
except:
pass
Source: https://stackoverflow.com/questions/18994334
How to ignore an exception and proceed?
Answer: The standard “nop” in Python is the pass
statement, Use this code.
try:
do_something()
except Exception:
pass
Using except Exception
instead of a bare except
avoid catching exceptions like SystemExit
, KeyboardInterrupt
etc.
Read: Python docs for the pass statement
Do comment if you have any doubts or suggestions on this Python exception-handling topic.
Note: IDE: PyCharm 2021.3.3 (Community Edition)
Windows 10
Python 3.10.1
All Python Examples are in Python 3, so Maybe its different from python 2 or upgraded versions.
Содержание:развернуть
- Немного информатики
- Синтаксис цикла while
- Несколько примеров использования цикла while
- break и continue
- else
- while true или бесконечный цикл
- Best practice
-
Цикл while в одну строку
-
Вложенные циклы
-
Как выйти с помощью break из двух циклов
Использование циклов предоставляет программисту возможность многократного исполнения определенного участка кода. Это один из основных рабочих инструментов любого разработчика, и практически ни одна из существующих программ не обходится без него.
Циклы в языке Python представлены двумя основными конструкциями: while
и for
. Цикл while
считается универсальным, в то время как for
нужен для обхода последовательности поэлементно.
Подробнее о циклах for вы можете прочитать здесь:
Так или иначе, обе конструкции одинаково применимы и являются важнейшими элементами любого высокоуровневого языка, в том числе и языка Python.
Немного информатики
Как было отмечено выше,
Цикл — это управляющая конструкция, которая раз за разом выполняет серию команд (тело цикла) до тех пор, пока условие для выполнения является истинным.
Напишем на псевдокоде классическую схему:
повторять, пока условие
начало цикла
последовательность инструкций
конец цикла
Конструкция начинает свою работу с проверки условия, и, если оно истинно, запускается цикл. На каждой новой итерации (единичный проход по циклу) условие продолжения проверяется вновь. Таким образом, последовательность инструкций будет исполняться до тех пор, пока это условие, наконец, не окажется ложным.
Циклы, как механизм программирования, нужны, главным образом, для упрощения написания кода. Вполне очевидно, что создавать программу, выполняющую определённую операцию для каждой точки 4К дисплея в отсутствии циклов — это вручную повторять описание нужной команды 4096*2160 раз. 🤔 Много? Безусловно.
Применение в этой задаче всего одного цикла позволит сократить длину кода, как минимум, на 6 порядков. А если представить, что ту же самую программу нужно переписать для 8К монитора, то, вместо изменения всего одной инструкции в счетчике цикла, вам придётся дописывать ещё пару десятков миллионов строк кода, что является попросту недопустимым по своей величине и трудозатратам объёмом.
Польза циклов ясна и очевидна. Обладая мощной выразительностью и ёмкой натурой, они, без сомнений, являются одним из фундаментальных конструктов высокоуровневого программирования. Каждому разработчику необходимо знать и понимать принципы их работы.
Синтаксис цикла while
В самом простом случае, цикл while
в python очень похож по своей структуре на условную конструкцию с if
:
import time
a = 1
if a == 1:
print("I'm the condition")
while a == 1:
print("I'm the loop")
time.sleep(1)
И в том и в другом случае, блок кода внутри (инструкция print(‘…’)
) будет исполнен тогда и только тогда, когда условие (a == 1)
будет иметь значение True
. Вот только в конструкции с if
, при успешной проверке, вывод на экран будет выполнен всего один раз, а в случае с while
фраза «I’m the loop» будет печататься бесконечно.
Такое явление называется бесконечным циклом. У них есть свои определенные смысл и польза, но их мы разберём чуть позже, поскольку чаще всего цикл всё-таки должен как-то заканчиваться. И вполне логично, что для его завершения нужно произвести определенные манипуляции с условием.
Переменная a
, в примере выше, называется управляющей (или счетчик). При помощи таких переменных можно контролировать момент выхода из цикла. Для этого их следует сравнить с каким-либо значением.
count = 1 # фиксируем начальное значение
while count <= 10: # и конечное (включительно)
print(count, end=' ')
count += 1
# после 9-й итерации в count будет храниться значение 10
# это удовлетворяет условию count <= 10, поэтому на 10-м витке будет выведено число 10
# (как видно, значение счетчика печатается до его инкрементирования)
# после count станет равным 11, а, значит, следующий прогон цикла не состоится, и он будет прерван
# в итоге получаем:
> 1 2 3 4 5 6 7 8 9 10
В Python есть и более сложные, составные условия. Они могут быть сколь угодно длинными, а в их записи используются логические операторы (not
, and
, or
):
dayoff = False
sunrise = 6
sunset = 18
worktime = 12
# пример составного условия
while not dayoff and sunrise <= worktime <= sunset:
if sunset == worktime:
print("Finally it's over!")
else:
print('You have ', sunset - worktime, ' hours to work')
worktime += 1
>
You have 6 hours to work
You have 5 hours to work
You have 4 hours to work
You have 3 hours to work
You have 2 hours to work
You have 1 hours to work
Finally it's over!
Как можно заметить, управляющая переменная вовсе не обязана являться счётчиком. Она может быть просто логической переменной, чье значение изменяется где-то в самом цикле:
num = 0
control = True
while num < 10:
num += 1
# аналогичная запись
num = 0
control = True
while control:
if num == 10:
control = False
num += 1
Стоит иметь в виду, что использование неинициализированной переменной в качестве управляющей цикла обязательно приведёт к возникновению ошибки:
# unknown до этого нигде не была объявлена
while unknown:
print('+')
>
Traceback (most recent call last):
while unknown:
NameError: name 'unknown' is not defined
Несколько примеров использования цикла while
Идея циклов while
проста — требуется определенное количество раз сделать что-то? Заведи счётчик и уменьшай/увеличивай его в теле цикла.
x = 20
y = 30
while x < y:
print(x, end=' ')
x = x + 3
> 20 23 26 29
Своеобразным счётчиком может быть даже строка:
word = "pythonchik"
while word:
print(word, end=" ")
# на каждой итерации убираем символ с конца
word = word[:-1]
> pythonchik pythonchi pythonch pythonc python pytho pyth pyt py p
break и continue
Оператор break
заставляет интерпретатор прервать выполнение цикла и перейти к следующей за ним инструкции:
counter = 0
while True:
if counter == 10:
break
counter += 1
Цикл прервётся после того, как значение счетчика дойдёт до десяти.
Существует похожий оператор под названием continue
, однако он не прекращает выполнение всей конструкции, а прерывает лишь текущую итерацию, переходя затем в начало цикла:
# классический пример вывода одних лишь чётных значений
z = 10
while z:
z -= 1
if z % 2 != 0:
continue
print(z, end=" ")
> 8 6 4 2 0
Эти операторы бывают весьма удобны, однако плохой практикой считается написание кода, который чересчур ими перегружен.
else
В Python-циклах часть else
выполняется лишь тогда, когда цикл отработал, не будучи прерван break
-ом.
В реальной практике, else
в циклах применяется нечасто. Такая конструкция отлично сработает, когда будет необходимо проверить факт выполнения всех итераций цикла.
👉 Пример из практики: проверка доступности всех выбранных узлов сети
Например, обойти все узлы локальной сети и
def print_prime_list(list_of_numbers: list) -> None:
""" функция выведет список чисел,
если каждое из этих чисел является простым """
number_count = len(list_of_numbers) # количество чисел
i = 0
while i < number_count:
x = list_of_numbers[i] // 2
if x != 0 and list_of_numbers[i] % x == 0:
break
i += 1
else:
print(f'{list_of_numbers} - list is prime!')
print_prime_list([11, 100, 199]) # 100 - не простое число
>
print_prime_list([11, 113, 199])
> [11, 113, 199]
В каком-либо другом языке стоило бы завести булеву переменную, в которой хранится результат проверки, но у Python, как всегда, есть способ получше!
while true или бесконечный цикл
В большинстве случаев, бесконечные циклы появляются из-за логических ошибок программиста (например, когда условие цикла while
при любых вариантах равно True
). Поэтому следует внимательно следить за условием, при котором цикл будет завершаться.
Однако вы некоторых случая бесконечный цикл делают намерено:
- Если нужно производить какие-то действия с интервалом, и выходить из цикла лишь в том случае, когда внутри тела «зашито» условие выхода.
Пример: функция, которая возвращаетconnection
базы данных. Если связь с базой данных отсутствует, соединение будет пытаться (в цикле) установиться до тех пор, пока не установится. - Если вы пишете полноценный демон, который продолжительное время висит как процесс в системе и периодически производит какие-то действия. В таком случае остановкой цикла будет прерывание работы программы. Пример: скрипт, который раз в 10 минут «пингует» IP адреса и пишет в лог отчет о доступности этих адресов.
💁♂️ Совет: в бесконечных циклах рекомендуется ставить таймаут выполнения после каждой итерации, иначе вы очень сильно нагрузите CPU
:
import time
while True:
print("Бесконечный цикл")
time.sleep(1)
>
Бесконечный цикл
Бесконечный цикл
Бесконечный цикл
Traceback (most recent call last):
File "main.py", line 5, in <module>
time.sleep(1)
KeyboardInterrupt
Aborted!
Код был прерван комбинацией клавиш ^Ctrl
+ C
. Иначе цикл продолжался бы бесконечно.
Best practice
Цикл while в одну строку
Для составных конструкций (таких, где нужен блок с отступом), можно этот отступ убрать, но только если в блоке используются простые операторы. Отделяются они всё также двоеточием.
Например, записи:
while x < y:
x +=1
# и
while x < y: x += 1
будут считаться эквивалентными, и при чтении второй из них интерпретатор не будет выдавать ошибку.
Вложенные циклы
Вложенные while
циклы встречаются не так часто, как их братья (или сестры) for
, что, однако не мешает им быть полезными. Простой пример — выведем на экран таблицу умножения:
q = 1
while q <= 9:
w = 1
while w <= 9:
print(q * w, end=" ")
w += 1
q += 1
print("")
>
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81
Нет никаких проблем с использованием вложенных циклов while
, однако стоит иметь в виду, что вложения свыше третьего уровня будут уже практически нечитаемыми для человека.
Как выйти с помощью break из двух циклов
В случае вложенных циклов, оператор break
завершает работу только того цикла, внутри которого он был вызван:
i = 100
j = 200
while i < 105:
while j < 205:
if j == 203:
break
print('J', j)
j += 1
print('I', i)
i += 1
>
J 200
J 201
J 202
# здесь видно, что внутренний цикл прерывается, но внешний продолжает работу
I 100
I 101
I 102
I 103
I 104
В Python не существует конструкций, которая прерывала бы сразу несколько циклов. Но есть как минимум 3 способа, которыми можно реализовать данное поведение:
Способ №1
Используем конструкцию for ... else ...
:
def same_values_exists(list_1: list, list_2: list) -> None:
""" функция выводит на экран
первые совпавшие числа из списков """
for i in list_1:
for j in list_2:
print("compare: ", i, j)
if i == j:
print(f"found {i}")
break
else:
continue
break
same_values_exists([0, 10, -2, 23], [-2, 2])
>
compare: 0 -2
compare: 0 2
compare: 10 -2
compare: 10 2
compare: -2 -2
found -2
Если все итерации вложенного цикла сработают, выполнится else
, который скажет внешнему циклу продолжить выполнение. Если во внутреннем цикле сработает break
, сразу выполнится второй break
.
Способ №2
Через создание дополнительного флага:
def same_values_exists(list_1: list, list_2: list) -> None:
""" функция выводит на экран
первые совпавшие числа из списков """
break_the_loop = False
for i in list_1:
for j in list_2:
print("compare: ", i, j)
if i == j:
print(f"found {i}")
break_the_loop = True
break
if break_the_loop:
break
same_values_exists([0, 10, -2, 23], [-2, 2])
>
compare: 0 -2
compare: 0 2
compare: 10 -2
compare: 10 2
compare: -2 -2
found -2
Внешний цикл был прерван вслед за внутренним. Дело сделано!
Способ №3
Если циклы находятся в функции (как в нашем примере), достаточно просто сделать return
:
def same_values_exists(list_1: list, list_2: list) -> None:
""" функция выводит на экран
первые совпавшие числа из списков """
for i in list_1:
for j in list_2:
print("compare: ", i, j)
if i == j:
print(f"found {i}")
return
same_values_exists([0, 10, -2, 23], [-2, 2])
>
compare: 0 -2
compare: 0 2
compare: 10 -2
compare: 10 2
compare: -2 -2
found -2
—