我正在尝试开发一些代码,以在执行时间太长时继续重试函数调用。通过简单的测试,我的代码似乎可以很好地完成此任务,但是当我将其用于预期目的时,调用一个有时会超时(经过很长的时间,例如30分钟)的API,计时器不会似乎起作用。
基本设置和测试(使用循环减少每次迭代的睡眠时间)是
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,而我仍然陷入了a的原始问题单个API调用有时会花很长时间。
在这样的检查结构(保持上面的函数定义和导入)中对API的示例调用是:
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秒还要长),也不会打印“超时通过”,并且计时器也不会触发会重置调用的错误。知道为什么计时器在这种情况下似乎不起作用以及如何使它起作用的任何想法吗?