2015-06-29 4 views
1

Я запускаю приложение Python в Google App Engine, которое регулярно проверяет последние электронные письма для нескольких пользователей. Я заметил, что в случайные моменты API возвращает следующую ошибку:GMail API возвращает непонятную ошибку в случайные моменты

error: An error occured while connecting to the server: Unable to fetch URL: https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest?userIp=0.1.0.2 

Как правило, если работа выполняется снова, она работает. Ниже моего кода. Я хотел бы понять, что вызывает это, и что еще более важно, как я могу предотвратить ошибку от блокировки процесса (например, как снова запустить задание с теми же значениями, когда эта ошибка возникает).

class getLatest(webapp2.RequestHandler): 
    def post(self): 
    try: 
     email = self.request.get('email') 
     g = Credentials.get_by_id(email) 
     REFRESH_TOKEN = g.refresh_token 
     start_history_id = g.hid 

     credentials = OAuth2Credentials(None, settings.CLIENT_ID, 
          settings.CLIENT_SECRET, REFRESH_TOKEN, None, 
          GOOGLE_TOKEN_URI, None, 
          revoke_uri=GOOGLE_REVOKE_URI, 
          id_token=None, 
          token_response=None) 

     http = credentials.authorize(httplib2.Http()) 
     service = discovery.build("gmail", "v1", http=http) 
     for n in range(0, 5): 
     try: 
      history = service.users().history().list(userId=email, startHistoryId=start_history_id).execute(http=http) 
      break 
     except errors.HttpError, e: 
      if n < 4: 
      time.sleep((2 ** n) + random.randint(0, 1000)/1000) 
      else: 
      raise 
     changes = history['history'] if 'history' in history else [] 
     while 'nextPageToken' in history: 
     page_token = history['nextPageToken'] 
     for n in range(0, 5): 
      try: 
      history = service.users().history().list(userId=email, startHistoryId=start_history_id, pageToken=page_token).execute(http=http) 
      break 
      except errors.HttpError, e: 
      if n < 4: 
       time.sleep((2 ** n) + random.randint(0, 1000)/1000) 
      else: 
       raise 
     changes.extend(history['history']) 

    except errors.HttpError, error: 
     logging.exception('An error occurred: '+str(error)) 
     if error.resp.status == 401: 
      # Credentials have been revoked. 
      # TODO: Redirect the user to the authorization URL. 
      raise NotImplementedError() 
     else: 
      stacktrace = traceback.format_exc() 
      logging.exception('%s', stacktrace) 

UPDATE

Я обновил код на основе ниже ответа, однако он никогда не кажется, для запуска запроса многократно. Процесс просто прерывается, как только происходит исключение.

ответ

0

Оказалось, что это была проблема, о которой сообщалось here. Я нажимал ограничение скорости при запросе документа об открытии, который вам нужно делать только один раз в день. Я решил это, реализовав предлагаемое решение в своем приложении. Код может быть найден в this Stackoverflow question.

0

Эта ошибка может возникать из-за нескольких причин, в том числе когда ваш агент переходит в автономный режим на какое-то время, чтобы превысить ограничение скорости API Gmail. Вы должны повторить попытку в случае этих временных проблем изящным образом. Ниже приведен код редактирования, который может помочь:

class getLatest(webapp2.RequestHandler): 
    def post(self): 

try: 
    email = self.request.get('email') 
    g = Credentials.get_by_id(email) 
    REFRESH_TOKEN = g.refresh_token 
    start_history_id = g.hid 

    credentials = OAuth2Credentials(None, settings.CLIENT_ID, 
         settings.CLIENT_SECRET, REFRESH_TOKEN, None, 
         GOOGLE_TOKEN_URI, None, 
         revoke_uri=GOOGLE_REVOKE_URI, 
         id_token=None, 
         token_response=None) 

    http = credentials.authorize(httplib2.Http()) 
    service = discovery.build("gmail", "v1", http=http) 
    for n in range(0, 5): 
    try: 
     history = service.users().history().list(userId=email, startHistoryId=start_history_id).execute(http=http) 
     break 
    except Exception as e: 
     # Apply exponential backoff. 
     time.sleep((2 ** n) + random.randint(0, 1000)/1000) 

    changes = history['history'] if 'history' in history else [] 
    while 'nextPageToken' in history: 
    page_token = history['nextPageToken'] 

    for n in range(0, 5): 
    try: 
     history = service.users().history().list(userId=email, startHistoryId=start_history_id, pageToken=page_token).execute(http=http) 
     changes.extend(history['history']) 
     break 
    except Exception as e: 
     # Apply exponential backoff. 
     time.sleep((2 ** n) + random.randint(0, 1000)/1000) 
except errors.HttpError, error: 
    logging.exception('An error occurred: '+str(error)) 
    if error.resp.status == 401: 
     # Credentials have been revoked. 
     # TODO: Redirect the user to the authorization URL. 
     raise NotImplementedError() 
    else: 
     stacktrace = traceback.format_exc() 
     logging.exception('%s', stacktrace) 

По сути, это код повторных попыток, если исключение происходит в Google конце с той же точки с экспоненциальным снижением мощности. Добавьте код ошибки, для которого вы хотите повторить попытку. Надеюсь, это решит вашу проблему.

+0

Я предполагаю, что добавление перерыва также потребуется для того, чтобы не запускать тот же запрос успешно 5 раз? – Vincent

+0

@ Винсент, ты прав, исправил свой пост выше. Спасибо, что указали это. Он должен работать сейчас :) –

+0

К сожалению, мне пришлось снять флажок, так как ошибка все еще присутствует. Думал, что это ушло, но, к сожалению, это не так. Я добавил обновленный код выше. – Vincent

Смежные вопросы