2017-03-17 12 views
3

レート制限の例外GitHubを処理するコンテキストマネージャーを作成しようとしています。基本的には、エラーをリスンして、エラーが発生したときに、リセット時間(すべてはGitHub APIを通じて行われます)を動的にプルして、その時間を待ちます。どの時点で私はプログラムを再開し、この作業を完了するために必要な回数だけこれをやりたいのですか?代わりに、継続して周りに戻って旋回のContext ManagerでAPIレート制限を処理するにはどうすればよいですか?

@contextlib.contextmanager 
def api_rate_manager(api_obj: g3.GitHub): 
    # Check for the API ratelimit being exhausted. Limited to 5k 
    # requests per hour. 
    try: 
     yield 
    except GitHubError as e: 
     if 'rate limit exceeded' in e.msg.lower(): 
      info = g3.rate_limit()['resources']['core'] 
      reset = mu.convert_unix_timestamp(info.get('reset')) 
      delta = reset - datetime.now() 
      sleep(
       delta.seconds + 1) # Add a second to account for milliseconds 

現在のところ、それは正しくエラーをキャッチしてお待ちしておりますが、それは単に(理にかなって)プログラムを終了します。ここでは

は、私がこれまで持っているものです。コードにチェックを入れて残っている制限が何であるかを知ることができ、0に達したら待つが、コンテキストマネージャを練習したいと思った。これは以下のように使用されるであろう

 with api_rate_manager(gh): 
      for commit_iter in commit_iters: 
       handler: gu.EtagHandler = commit_iter.etag_handler 
       for commit in commit_iter: 
        if not commit: 
         continue 

        commit.refresh() 
        author_data: dict = commit.commit.author 
        data = { 
         'sha': commit.sha, 
         'author': author_data.get('name'), 
         'author_email': author_data.get('email'), 
         'create_date': author_data.get('date'), 
         'additions': commit.additions, 
         'deletions': commit.deletions, 
         'total': commit.total 
        } 
        mu.add_etl_fields(data) 
        writer.writerow(data) 
        has_data = True 
       etag: str = commit_iter.get_etag() 
       if etag: 
        logger.info(f'Etag for {commit_iter.name}: {etag}') 
        handler.store_in_db(etag=etag) 

答えて

1

コンテキストマネージャは、(発電機のように)yieldを使用するが、それは一度だけ発生します。 See contextlib's documentation

結果として、コンテキストマネージャで例外がキャッチされた場合、実行はyieldの後に再開し、終了します。 コンテキストマネージャとメイン反復の順序を逆にすることができます。下の私の例を見てください。

コンテキストマネージャ:

import contextlib 
from time import sleep 

@contextlib.contextmanager 
def api_rate_manager(): 
    try: 
     yield 
    except KeyError as e: 
     print('sleeping') 
     sleep(3) 

テストケース1:

a = {0:0,1:2,2:4,3:6,5:10} 

with api_rate_manager(): 
    for i in range(8): 
     print(a[i]) 

出力:

0 
2 
4 
6 
sleeping 

テストケース2:

for i in range(8): 
    with api_rate_manager(): 
     print(a[i]) 

出力:

0 
2 
4 
6 
sleeping 
10 
sleeping 
sleeping 
関連する問題