Передача информации в стек в Исключении? - PullRequest
2 голосов
/ 11 июня 2019

Я получаю исключение глубоко в некотором цикле в функции в длительном процессе. Если я получаю исключение, я хотел бы зарегистрировать вещь, которая находится в индексе в цикле, в котором произошло исключение. К сожалению, нужная мне информация не доступна в текущей функции ... она находится в следующей функции в стеке. Однако индекс не доступен в следующей функции вверх по стеку, он доступен только в текущей функции. Поэтому для записи соответствующей информации мне нужна информация из двух вызовов функций на разных уровнях вложенности. Как передать информацию между функциями в Exception?

Например:

def foo():
    information_I_need = ["some", "arbitrary", "things"]
    data_operated_on = list(range(0, 10*len(information_I_need), 10)) #0,10,20
    #NB: these two lists are the same size
    try:
        bar(data_operated_on)
    except ValueError as e:
        i = e.get_the_index_where_bar_failed()
        print(information_I_need[i])

def bar(aoi):
    for i in range(len(aoi)):
        try:
            fails_on_10(aoi[i])
        except ValueError as e:
            e.add_the_index_where_bar_failed(i)
            raise e

def fails_on_10(n):
    if n == 10:
        raise ValueError("10 is the worst!")

Ожидаемое поведение здесь будет таким, что вызов foo() печатает "arbitrary".

В этом примере bar содержит информацию (а именно, индекс i), которая необходима foo для правильного сообщения о проблеме. Как я могу получить эту информацию от bar до foo?

1 Ответ

3 голосов
/ 11 июня 2019

Вы можете добавить индекс в качестве атрибута объекта исключения.

Лучше всего делать это с помощью пользовательского класса исключений, а не использовать одно из встроенных исключений.

class BadInformation(Exception):
    def __init__(self, message, index):
        # py2/3 compat
        # if only targeting py3 you can just use super().__init__(message)
        super(BadInformation, self).__init__(message)
        self.bad_index = index

def foo():
    information_I_need = ["some", "arbitrary", "things"]
    data_operated_on = list(range(0, 10*len(information_I_need), 10)) #0,10,20
    #NB: these two lists are the same size
    try:
        bar(data_operated_on)
    except BadInformation as e:
        i = e.bad_index
        print(information_I_need[i])

def bar(aoi):
    # if you need both the index and value, use `enumerate()`
    for index, value in enumerate(aoi):
        try:
            fails_on_10(value)
        except ValueError as e:
            raise BadInformation(str(e), index)
            ## on py 3 you may want this instead
            ## to keep the full traceback
            # raise BadInformation(str(e), index) from e



def fails_on_10(n):
    if n == 10:
        raise ValueError("10 is the worst!")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...