2017-10-03 6 views
-1

생성기에서 코드를 반복하고 있습니다. 두 번째 반복이 끝나면 그 루프를 끝내야합니다. 이렇게하려면 Generator.close() 메서드를 호출 할 때 GeneratorExit을 발생시키는 break을 사용합니다.생성기 루프를 깨는 우아한 방법 : 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을 사용합니다. 따라서 각 반복에서 쿼리를 처리합니다. 두 번째 또는 세 번째 반복 (쿼리는 일반적으로 200 개의 행을 반환하지만 더 적을 수도 있음) 이후에 발생할 수있는 최소 400 개의 상태에 도달하면 쿼리를 중지하려고합니다. 여기서 제너레이터 슬라이스는 옵션이 아닙니다. 모든 쿼리를 처리하지 않으려면 (약 16 * 200 = 3200 상태의 경우 총 16 개) 400 개의 상태가 반환 된 후에 코드를 중단하여 정확히 피하고자합니다.

편집 : generator.close() 제기하는 GeneratorExit 예외 무시

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

발전기 : 더 나은 이해를 위해, 여기 내 발전기에 대한 코드입니다. BaseException을 붙잡음으로써 효과적으로 폐쇄를 불가능하게 만들었으므로 발전기가 대신 은 다른 값인을 산출합니다. yield에 다시 도달 할 때까지 예외 처리기가 루프의 맨 위로 이동하기 때문에 코드가 계속됩니다. 따라서 예외가 표시되는 이유는 다음과 같습니다.

발전기가 값을 산출하면 RuntimeError이 발생합니다.

코드에 BaseException을 넣지 마십시오. Exception, 기껏 특정 예외을 잡아 나 :

except Exception a e: 
    # ... 

그런 식으로 당신이 GeneratorExit (BaseException의 서브 클래스), SystemExit 또는 KeyboardInterrupt를 잡을 수 없습니다.

이 시점에서 코드가 SystemExitKeyboardInterrupt이어야한다고 생각되면 최소한 except BaseException as e: 처리기 전에 except GeneratorExit: return을 추가하십시오.

관련 문제