Уведомления

Группа в Telegram: @pythonsu

#1 Апрель 28, 2011 07:04:48

shupg
От:
Зарегистрирован: 2009-08-07
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

Продолжать выполнение скрипта несмотря на ошибки

Доброе время суток. Есть задача выполнить несколько проверок так, чтобы точно каждая хотя бы попробовала. О чем речь:

try:
func1(1)
finally:
try:
func2(2,3)
finally:
func3(4,5,6)
func4()
func1()
Таких вложенных finally бывает под десяток. Соответственно, читабельность кода и удобство добавление таких проверок сильно страдает.

Хотелось бы так:
with try_finally:
func1(1)
with try_finally:
func2(2,3)
raise_all_exceptions()
Буду рад любым полезным советам.



Офлайн

#2 Апрель 28, 2011 07:35:00

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Продолжать выполнение скрипта несмотря на ошибки

Все еще непонятно. Вы можете приложить небольшую *работающую* иллюстрацию?
А то как-то не видно:
— Какой характер у функций-проверок?
— Нужно ли возвращаемое ими значение?
— Что ожидается в результате, если func1 или func2 выбросят исключение?

В зависимости от перечисленного (а может и другие вопросы появятся) советы будут разными.



Офлайн

#3 Апрель 28, 2011 07:42:10

shupg
От:
Зарегистрирован: 2009-08-07
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

Продолжать выполнение скрипта несмотря на ошибки

— Какой характер у функций-проверок?
Не понимаю какое это это имеет значение. Пусть там идет много кода, потом assert.

— Нужно ли возвращаемое ими значение?
Нет

— Что ожидается в результате, если func1 или func2 выбросят исключение?
сохранять это исключение до вызова raise_all_exceptions(), где бросать все исключения разом



Офлайн

#4 Апрель 28, 2011 09:50:14

agalen
От:
Зарегистрирован: 2011-03-23
Сообщения: 185
Репутация: +  17  -
Профиль   Отправить e-mail  

Продолжать выполнение скрипта несмотря на ошибки

Можно сделать функцию для перехвата исключений.
Примерно так:

def safe_call( func, ex_list, *args, **kw ):
try:
func( *args, **kw )
except:
ex_list.append( sys.exc_info() )

ex_list = []
safe_call( func1, ex_list, 1 )
safe_call( func2, ex_list, 1, 2, 3 )
proc_exceptions( ex_list )



Офлайн

#5 Апрель 28, 2011 09:58:50

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Продолжать выполнение скрипта несмотря на ошибки

Поверьте, код-иллюстрация очень помогает.
Тем не менее.

Делаю все в цикле.
Проверяю каждый тест, подсовывая ему значения. Нечто вроде прохода по списку пар: функция и аргументы.
Потом.. Хмм. Не понял, что значит “бросать все исключения разом”. Но исключения можно словить и потом с ними что-то сделать.

Еще раз повторяю (вы не поверите, как часто приходится этим заниматься): постройте пример с вашими try… finally. Вложенностью на три-четыре.
Покажите на нем, что хотите и чего не хотите. Это поможет вам и мне (как отвечающему). Лезть в детали реализации тестовых функций не нужно.
Сведите пример до простого исполняемого кода. Я его запускаю — вижу результат. Правлю — и вы видите мои предложения.



Офлайн

#6 Апрель 28, 2011 10:32:37

shupg
От:
Зарегистрирован: 2009-08-07
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

Продолжать выполнение скрипта несмотря на ошибки

Код:

import time, sys

class Agent():
def doAction(self):
print "Agent.doAction"
def clear(self):
print "Agent.clear"
def check(self):
return "Agent.check"

class Customer():
def clear(self):
print "Customer.clear"

class Admin():
def doAction(self):
print "Admin.doAction"


class Cl():
def __init__(self):
self.admin = Admin()
self.customer = Customer()
self.agent = Agent()
self.permission = (0,1)
self.permissions = dict((((1,2), True), ((3), True),((4), True),((0), True),))


def clean(self):
a,b,c,d,e = range(5)
c_id = condition = None

try:
print 1
if self.customer:
self.customer.clear()
if self.agent:
self.agent.clear()
err = self.agent.check()
if err:
print >> sys.stderr, "Exception 1"
raise Exception("Exception 1")
finally:
if self.permission in ((a, b), c, d, e):
try:
print 2
if self.permission == (a, b):
try:
print 3
self.admin.doAction()
print >> sys.stderr, "Exception 2"
raise Exception("Exception 2")
finally:
if self.permission == c:
self.agent.doAction()
finally:
try:
print 4
reason = None if condition else 'Q'
self.agent.doAction()

time.sleep(1)
state = self.agent.doAction()
if state != 'P':
print 'Tried one more time'
self.agent.doAction()
if False:
print >> sys.stderr, "Exception 3"
raise Exception("Exception 3")
finally:
if self.permission == (a, b):
self.agent.doAction()
print >> sys.stderr, "Exception 4"
raise Exception("Exception 4")

Cl().clean()
Есть потребность: упростить все try-finally ибо они будут расти



Отредактировано (Апрель 29, 2011 15:03:28)

Офлайн

#7 Апрель 30, 2011 08:03:50

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Продолжать выполнение скрипта несмотря на ошибки

Не то чтобы я был счастлив решением — но работает.

import time, sys

class Agent():
def doAction(self):
print "Agent.doAction"
def clear(self):
print "Agent.clear"
def check(self):
return "Agent.check"

class Customer():
def clear(self):
print "Customer.clear"

class Admin():
def doAction(self):
print "Admin.doAction"

class Eater(object):

def __init__(self):
self.exc = None

def __enter__(self):
return self

def __exit__(self, exc_type, exc_val, exc_tb):
if exc_val is not None:
self.exc = exc_val
return True

def finish(self):
if self.exc is not None:
raise self.exc


class Cl(object):
def __init__(self):
self.admin = Admin()
self.customer = Customer()
self.agent = Agent()
self.permission = (0,1)
self.permissions = dict((((1,2), True),
((3), True),
((4), True),
((0), True),))


def clean(self):
a, b, c, d, e = range(5)
c_id = condition = None

try:
print 1
if self.customer:
self.customer.clear()
if self.agent:
self.agent.clear()
err = self.agent.check()
if err:
print >> sys.stderr, "Exception 1"
raise Exception("Exception 1")
finally:
if self.permission in ((a, b), c, d, e):
try:
print 2
if self.permission == (a, b):
try:
print 3
self.admin.doAction()
print >> sys.stderr, "Exception 2"
raise Exception("Exception 2")
finally:
if self.permission == c:
self.agent.doAction()
finally:
try:
print 4
reason = None if condition else 'Q'
self.agent.doAction()

time.sleep(1)
state = self.agent.doAction()
if state != 'P':
print 'Tried one more time'
self.agent.doAction()
if False:
print >> sys.stderr, "Exception 3"
raise Exception("Exception 3")
finally:
if self.permission == (a, b):
self.agent.doAction()
print >> sys.stderr, "Exception 4"
raise Exception("Exception 4")

def do(self):
eater = Eater()
a, b, c, d, e = range(5)
c_id = condition = None

with eater:
print 1
if self.customer:
self.customer.clear()
if self.agent:
self.agent.clear()
err = self.agent.check()
if err:
print >> sys.stderr, "Exception 1"
raise Exception("Exception 1")

with eater:
if self.permission in ((a, b), c, d, e):
with eater:
print 2
if self.permission == (a, b):
with eater:
print 3
self.admin.doAction()
print >> sys.stderr, "Exception 2"
raise Exception("Exception 2")
with eater:
if self.permission == c:
self.agent.doAction()
with eater:
print 4
reason = None if condition else 'Q'
self.agent.doAction()

time.sleep(1)
state = self.agent.doAction()
if state != 'P':
print 'Tried one more time'
self.agent.doAction()
if False:
print >> sys.stderr, "Exception 3"
raise Exception("Exception 3")
with eater:
if self.permission == (a, b):
self.agent.doAction()
print >> sys.stderr, "Exception 4"
raise Exception("Exception 4")

eater.finish()


import sys
sys.stderr = sys.stdout # drop stdio buffering effect

try:
Cl().clean()
except:
import traceback; traceback.print_exc()

print '-' * 20
Cl().do()



Офлайн

#8 Май 5, 2011 07:33:31

shupg
От:
Зарегистрирован: 2009-08-07
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

Продолжать выполнение скрипта несмотря на ошибки

Пасиба за направление!



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version