2014-11-04 2 views
0

Я хотел бы реализовать отложенное исключение в Python, которое нормально хранить где-то, но как только оно каким-либо образом используется, оно вызывает исключение, которое было отложено. Что-то вроде этого:реализация отложенного исключения в Python

# this doesn't work but it's a start 
class DeferredException(object): 
    def __init__(self, exc): 
     self.exc = exc 
    def __getattr__(self, key): 
     raise self.exc 

# example: 

mydict = {'foo': 3} 
try: 
    myval = obtain_some_number() 
except Exception as e: 
    myval = DeferredException(e) 
mydict['myval'] = myval 

def plus_two(x): 
    print x+2 

# later on... 
plus_two(mydict['foo'])  # prints 5 
we_dont_use_this_val = mydict['myval'] # Always ok to store this value if not used 

plus_two(mydict['myval']) # If obtain_some_number() failed earlier, 
          # re-raises the exception, otherwise prints the value + 2. 

Вариант использования заключается в том, что я хочу написать код для анализа некоторых значений из входящих данных; если этот код выходит из строя, но результаты никогда не используются, я хочу, чтобы он терпел неудачу; если он терпит неудачу, но результаты будут использованы позже, то я бы хотел, чтобы не распространялся.

Любые предложения о том, как это сделать? Если я использую мой класс DeferredException я получаю этот результат:

>>> ke = KeyError('something') 
>>> de = DeferredException(ke) 
>>> de.bang         # yay, this works 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 6, in __getattr__ 
KeyError: 'something' 
>>> de+2          # boo, this doesn't 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unsupported operand type(s) for +: 'DeferredException' and 'int' 
+0

Я полагаю, ваша функция может вернуть функцию, которая либо генерирует значения, либо вызывает ошибку, но в противном случае я не вижу, как вы могли это сделать. – jonrsharpe

+4

Ну, вы можете перегрузить * все * специальные функции ('__add__',' __call__' и т. Д.) ... Я не уверен, что мне нравится эта идея отложенного исключения, хотя - конечно, это неожиданно для исключений в безобидном коде, удаленном от того, где произошла фактическая ошибка? – Cameron

+0

Почему бы не сохранить состояние/использовать блоки 'finally' вместо того, чтобы пытаться сделать что-то магическое. – wim

ответ

1

Читать раздел 3.4.12 из документации, «Специальный поиск методы для новых классов.» Это точно объясняет проблему, с которой вы столкнулись. Обычный поиск атрибутов обходит интерпретатор для определенных операторов, например, добавление (как вы выяснили, жесткий путь). Таким образом, выражение de + 2 в вашем коде никогда не вызывает функцию getattr.

Единственное решение, согласно этому разделу, заключается в том, чтобы «специальный метод должен быть установлен на самом объекте класса, чтобы интерпретировать интерпретатор последовательно».

Возможно, вам лучше сохранить все ваши отложенные исключения в глобальном списке, завернув всю вашу программу в команду try: finally: и распечатав весь список в блоке finally.

+0

Итак, быстрое решение для python-2.7 - это переход к классу DeferredException: style. В соответствии с 3.4.11, поиск всегда выполняется в этом случае, и 'de + 2' будет вести себя по желанию. –

+0

Оперативные слова «быстрая и грязная», поскольку это решение было бы несовместимо с Python 3. Но если он решает вашу непосредственную проблему, пусть будет так. –

Смежные вопросы