2015-04-02 2 views
3

В моей программе у меня есть функция, которая обрабатывает вызовы requests и либо возвращает обработанный вызов, либо вызывает исключение. Эта функция используется многими другими функциями, однако проблема, с которой я сталкиваюсь, заключается в том, как обрабатывать исключение, которое может быть поднято. В настоящее время устанавливается, как так (упрощенно):Python: Есть ли способ заставить родительскую функцию вернуться?

def getFromAPI(url): 
    # create variable headers 
    r = requests.get(url, headers=headers) 
    if r.status_code == 404: 
     raise Exception("Error raised") 
    else: 
     #process data 
     return data 

def functionone(): 
    ... 
    try: 
     data = getFromAPI(url) 
    except Exception as e: 
     return handleException(e) 
     #handles problems, returns exception-formatted data 

    ... 
    # formatting data specific to functionone 
    return formatted_data 

def functiontwo(): 
    ... 
    try: 
     data = getFromAPI(url) 
    except Exception as e: 
     return handleException(e) 
     #handles problems, returns exception-formatted data 

    ... 
    # formatting data specific to functiontwo 
    return formatted_data 

def functionthree(): 
    ... 
    #similar to functionone and functiontwo 

Хотя я не думаю, что это не так, сами по себе, так как getFromAPI используется во многих функциях, имея постоянно повторять попытку кроме выписок чувствует себя неправильно , как если бы он выполнялся в функции getFromAPI. Однако, поскольку другие functionone до function_n все возвращают разные вещи в зависимости от того, была ли поднята ошибка, я не вижу способа справиться с этим из-за getFromAPI, если только нет способа для getFromAPI, чтобы заставить родительскую функцию возвращать, без явно вызывающий return в родительской функции.

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

+0

Позвольте ему громко выйти и поймать его дальше ... не справляйтесь с проблемой в каждой функции –

+0

К сожалению, у меня нет контроля над функциями дальше. – echolocation

+0

Под «далее вверх» подразумеваются вызывающие функции 'functionone'..'functionthree'? Или прямыми абонентами 'getFromAPI'? – kdopen

ответ

8

Написать декоратора, как этот

def catchAPIException(func): 
    def wrapper(*args, **kwargs) 
     try: 
      return func(*args, **kwargs) 
     except getFromAPIException as e: 
      return handleException(e) 
    return wrapper 

Тогда ваш functionone и т.д. просто выглядеть

@catchAPIException 
def functionone(): 
    ... 
    data = getFromAPI(url) 
    ... 
    # formatting data specific to functionone 
    return formatted_data 

Но вы хотите, чтобы поднять очень специфический обычай исключение, так что ваш декоратор воли только поймать соответствующий. Или, возможно, вы должны создать несколько различных исключений, которые могут обрабатываться по-разному.

Если разные функции хотят форматировать исключение по-своему, декоратору может быть передана другая функция, которая фактически используется для ее форматирования. То есть сделать handleException параметр для catchAPIException

def catchAPIException(exceptionHandler = handleException): 
    def real_decorator(func): 
     def wrapper(*args, **kwargs) 
      try: 
       return func(*args, **kwargs) 
      except getFromAPIException as e: 
       return exceptionHandler(e) 
     return wrapper 
    return real_decorator 

то функции, которые счастливы с обработчиком исключений по умолчанию объявляются так:

@catchAPIException 
def function1(): 
    ... 

Другие с более конкретными потребностями могут сделать это:

def customExceptionHandler(e): 
    ... 

@catchAPIException(customExceptionHandler) 
def function2(): 
    ... 

Если вы не знакомы с декораторами, вот reasonable tutorial и есть документы Python, хотя они не имеют явного s на них.

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