Повторите вызов функции, если занимает слишком много времени - PullRequest
0 голосов
/ 28 февраля 2019

Я пытаюсь разработать некоторый код, чтобы повторять попытку вызова функции, если выполнение занимает слишком много времени.У меня есть код, который, по-видимому, хорошо работает для этой задачи с простыми тестами, но когда я использую его по назначению, вызывая API, который время от времени истекает (через очень долгое время, например, 30 минут), таймер не 't, кажется, работает.

Базовая настройка и тестирование (с использованием цикла, который сокращает время ожидания на каждой итерации):

from contextlib import contextmanager
import threading
import _thread
from datetime import datetime
import time

class TimeoutException(Exception):
    def __init__(self, msg=''):
        self.msg = msg

@contextmanager
def time_limit(seconds, msg=''):
    timer = threading.Timer(seconds, lambda: _thread.interrupt_main())
    timer.start()
    try:
        yield
    except KeyboardInterrupt:
        raise TimeoutException("Timed out for operation {}".format(msg))
    finally:
        # if the action ends in specified time, timer is canceled
        timer.cancel()


ii=3
result = None
while result is None:
    try:
        with time_limit(1, 'sleep'):
            print('A ' + datetime.now().strftime("%H:%M:%S"))
            time.sleep(ii)
            result=2.71828
    except:
        print('Timeout pass')
        ii=ii-1
        pass
print('B ' + datetime.now().strftime("%H:%M:%S"))

Это работает, как и ожидалось.Однако, когда я заменяю контрольный пример вызовом API, с которым я работаю (https://github.com/swar/nba_api), таймер никогда не перехватывает API, когда он истекает, и я все еще застрял с первоначальной проблемойодин вызов API иногда занимает вечность.

Пример вызова API внутри такой структуры проверки (с сохранением вышеуказанных функций defs и import):

from nba_api.stats.endpoints import boxscoreadvancedv2

successful=None
    while successful is None:
        try:
            with time_limit(4,'sleep'):
                cur_boxsc_adv=boxscoreadvancedv2.BoxScoreAdvancedV2(game_id='0028000934').get_normalized_dict()
                successful=3.1415
        except:
            print('Timeout pass')
            pass

В этом случае, даже есливызов API занимает 20 минут (что на самом деле больше, чем 4 секунды, на которые я установил таймер). «Тайм-аут» никогда не печатается, и таймер никогда не вызывает ошибку, которая могла бы сбросить вызов. Любая идея, почему таймер не работаетПохоже, работает для этого случая и какие-либо идеи о том, как заставить его работать?

...