Найти - Пользователи
Полная версия: Продолжать выполнение скрипта несмотря на ошибки
Начало » Python для экспертов » Продолжать выполнение скрипта несмотря на ошибки
1
shupg
Доброе время суток. Есть задача выполнить несколько проверок так, чтобы точно каждая хотя бы попробовала. О чем речь:

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()
Буду рад любым полезным советам.
Андрей Светлов
Все еще непонятно. Вы можете приложить небольшую *работающую* иллюстрацию?
А то как-то не видно:
— Какой характер у функций-проверок?
— Нужно ли возвращаемое ими значение?
— Что ожидается в результате, если func1 или func2 выбросят исключение?

В зависимости от перечисленного (а может и другие вопросы появятся) советы будут разными.
shupg
— Какой характер у функций-проверок?
Не понимаю какое это это имеет значение. Пусть там идет много кода, потом assert.

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

— Что ожидается в результате, если func1 или func2 выбросят исключение?
сохранять это исключение до вызова raise_all_exceptions(), где бросать все исключения разом
agalen
Можно сделать функцию для перехвата исключений.
Примерно так:
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 )
Андрей Светлов
Поверьте, код-иллюстрация очень помогает.
Тем не менее.

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

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

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 ибо они будут расти
Андрей Светлов
Не то чтобы я был счастлив решением — но работает.
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()
shupg
Пасиба за направление!
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB