Отлов исключений, поднятых в гринлетах

Я пытаюсь поймать исключения, возникающие в гринлетах. Согласно этому руководству, к сожалению, "исключения, поднятые в Greenlet, остаются внутри Greenlet". В приведенном ниже коде у меня есть метод синхронизации, который порождает гринлеты сканирования. Эти гринлеты сканирования вызывают исключение HTTPError, которое мне нужно перехватить в теле метода синхронизации. На основе исключения в методе синхронизации я установлю соответствующий статус объекта Account. Любая идея, как я могу поймать исключения, вызванные гринлетами в методе синхронизации, чтобы выполнить это? Заранее спасибо!

# this is standalone helper method
def crawl(item):
    try:
        item.refresh_children(False) # THROWS HTTPError exception
        greenlets = [gevent.spawn_link_exception(crawl, child) for child in item.children]
        gevent.joinall(greenlets)
    except HTTPError, e:
        print e.message
        raise e
    except (JSONDecodeError, InvalidCredentialsException) as e:
        print e.message
        raise e

# this is instance method of the Account class 
def sync(self):
    "Sync search index with data from source"
    try:
        greenlets = [gevent.spawn_link_exception(crawl, item) for item in self.get_navigation()]
        gevent.joinall(greenlets)
        self.date_synced = datetime.datetime.now()
        self.save()
    except HTTPError, e:
        if e.status_code == 401:
            self.status = 'revoked'
        else:
            self.status = 'error'
        self.save()
    except LinkedFailed, e:
        print e.message
        exception_name = e.message.split()[-1]
        if exception_name in ['HTTPError', 'JSONDecodeError']:
            self.status = 'error'
            self.save()
        elif exception_name == 'InvalidCredentialsException':
            self.status = 'revoked'
            self.save()

person Arman    schedule 12.04.2013    source источник


Ответы (1)


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

def sync(self):
    "Sync search index with data from source"
    greenlets = [gevent.spawn_link_exception(crawl, item) for item in self.get_navigation()]
    gevent.joinall(greenlets)
    try:
        results = [greenlet.get() for greenlet in greenlets]
    except HTTPError, e:
        if e.status_code == 401:
            self.status = 'revoked'
        else:
            self.status = 'error'
        self.save()
    except LinkedFailed, e:
        print e.message
        exception_name = e.message.split()[-1]
        if exception_name in ['HTTPError', 'JSONDecodeError']:
            self.status = 'error'
            self.save()
        elif exception_name == 'InvalidCredentialsException':
            self.status = 'revoked'
            self.save()

    self.date_synced = datetime.datetime.now()
    self.save()
person Philip Cristiano    schedule 21.04.2013