kam*_*twa 12 python contextmanager
在我的utility.py中,我有,
@contextmanager
def rate_limit_protection(max_tries=3, wait=300):
tries = 0
while max_tries > tries:
try:
yield
break
except FacebookRequestError as e:
pprint.pprint(e)
if e._body['error']['message'] == '(#17) User request limit reached':
print("waiting...")
time.sleep(wait)
tries += 1
Run Code Online (Sandbox Code Playgroud)
在我的task.py中,我打电话给:
for date in interval:
with utility.rate_limit_protection():
stats = account.get_insights(params=params)
Run Code Online (Sandbox Code Playgroud)
在执行给定日期范围的任务后,一旦Facebook速率限制启动,程序将等待300秒,然后失败并显示错误.
File "/Users/kamal/.pyenv/versions/3.4.0/lib/python3.4/contextlib.py", line 78, in __exit__
raise RuntimeError("generator didn't stop")
RuntimeError: generator didn't stop
Run Code Online (Sandbox Code Playgroud)
Kev*_*vin 22
该with语句不是循环结构.它不能用于重复执行代码.创建的上下文管理器@contextmanager应该只应该yield一次.
上下文管理器(基本上)做了三件事:
如果你想做这样的事情,你需要重写它,以便循环移动到上下文管理器之外,或者根本没有上下文管理器.
一种选择是编写一个接受回调作为参数的函数,然后在循环中调用回调,就像你在上下文管理器中那样:
def do_rate_protection(callback, max_tries=3):
tries = 0
while max_tries > tries:
try:
callback()
break
except FacebookRequestError as e:
# etc.
Run Code Online (Sandbox Code Playgroud)
然后你可以像这样调用它:
for date in interval:
def callback():
# code
do_rate_protection(callback)
Run Code Online (Sandbox Code Playgroud)
如果回调不需要date变量,则可以将其移出循环以避免重复重新创建相同的函数(这会浪费资源).您还可以创建函数date的参数callback()并使用它来传递它functools.partial.
| 归档时间: |
|
| 查看次数: |
4679 次 |
| 最近记录: |