2017-10-03 12 views
-1

ジェネレータでコードをループしています。私は2番目の反復の後にループを壊す必要があります。これを行うには、を使用します。Generator.close()メソッドを呼び出すと、GeneratorExitが発生します。ジェネレータループを破る優雅な方法:GeneratorExitエラー

for page in limit_handled(tweepy.Cursor(..., ..., ...): 
    while len(the_list) < 400: 
     for status in page: 

      def process_status(tweet): 
       ... 
       ... 

      the_list.append(process_status(status)) 

    break 

このようなエラーを回避するより洗練された方法がありますか?

Exception ignored in: <generator object limit_handled at 0x000000003AB300A0> 
RuntimeError: generator ignored GeneratorExit 

私はこれら二つの質問への回答見てきました:How to take the first N...How to get the n next...をが、これは同じ問題ではありません。私の場合、GeneratorCursorを使用しています。したがって、各反復において、クエリを処理する。 2回目または3回目の繰り返し後に発生する可能性のある少なくとも400のステータスに達したら、クエリを停止したい(クエリは一般的に200行を返しますが、それも少なくなる可能性があります)。ここではジェネレーターのスライシングはオプションではありません。すべてのクエリ(約16 * 200 = 3200のステータスの場合は合計16個)を処理しないようにするのは、400個のステータスが返された後にコードを破棄することによって回避したいものです。

編集:より良く理解するために、ここで私の発電機のためのコードは次のとおりです。

def limit_handled(cursor): 
    global user_timeline_remaining 
    while True: 
     if user_timeline_remaining>1: 
      try: 
       yield cursor.next() 
      except BaseException as e: 
       print('failed_on_CURSOR_NEXT', str(e)) 
     else: 
      time.sleep(5*60) 
       try: 
        data = api.rate_limit_status() 
       except BaseException as f: 
        print('failed_on_LIMIT_STATUS', str(f)) 
       user_timeline_remaining = data['remaining_queries'] 
+0

ジェネレータで例外を処理してみませんか? 'try:... GeneratorExit:pass'以外のものです。 –

+0

'close()'は 'for'ループによって(直接)呼び出されません。ジェネレータオブジェクトに参照が残っていないときに呼び出されます(' for'ループが唯一の参照である場合、ループが終了すると、リファレンスが削除され、ジェネレータは削除されます)。 –

+0

残念ですが、ブレークが呼ばれたときに発生したことが明らかでした(ジェネレータの反復が残っていることを意味します) – ylnor

答えて

2

あなたのジェネレータgenerator.close()を提起することをGeneratorExit例外を無視します。 BaseExceptionをキャッチすると効果的に閉じることができなくなりますので、代わりにに別の値が返されます(yieldに再び到達するまでループの先頭に例外ハンドラの後にコードが続きます)。これがあなたの例外を見る理由です:

ジェネレータが値を生成する場合、RuntimeErrorが発生します。

実際にコードにBaseExceptionをキャッチしないでください。 Exception、せいぜい、特定の例外をキャッチか:

except Exception a e: 
    # ... 

そのようにあなたがGeneratorExitBaseExceptionのサブクラス)、SystemExitまたはKeyboardInterruptをキャッチしないでください。

あなたのコードは、少なくともあなたのexcept BaseException as e:ハンドラの前except GeneratorExit: returnを追加し、この時点でSystemExitKeyboardInterruptをキャッチしなければならないと感じた場合。

関連する問題