В настоящее время я разрабатываю приложение App Engine с использованием API Drive v3, но этот вопрос относится к большинству API Google.
Поскольку Drive API работает медленно в некоторых операциях, я хочу разделить каждую обработку файлов на разные задачи. Для этого я использую отложенную библиотеку, чтобы избежать сериализации-десериализации параметров.
Основным параметром является уже авторизованный служебный объект Drive API (с использованием служебных учетных записей и полномочий на уровне домена) для данного пользователя.
Упрощенный фрагмент кода выглядит так:
class Main(webapp2.RequestHandler):
def get(self):
# Authorize and get the Drive service
service = get_drive_service(keyfile, '[email protected]')
# Iterate through all the (previously retrieved) file list
for file_id in file_list:
# Queue a new task by passing the function and its arguments
deferred.defer(test_drive_service, service, file_id)
def test_drive_service(service, file_id):
# Do a simple Drive operation
response = service.files().get(fileId=file_id).execute()
print response.get('name')
и часть моего файла app.yaml:
handlers:
- url: /_ah/queue/deferred
script: google.appengine.ext.deferred.deferred.application
login: admin
builtins:
- deferred: on
Если я не использую deferred.defer()
и вызываю функцию test_drive_service()
напрямую, проблем не возникает, и я правильно получаю нужный файл и информацию.
Однако при использовании отложенной библиотеки возникает следующая ошибка:
HttpError: <HttpError 403 when requesting (...) returned "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.">
Моя квота в порядке, поэтому дневной лимит действительно не исчерпан.
Что может быть причиной проблемы? Есть ли другой конкретный способ правильно передать объект службы в очередь задач?
ИЗМЕНИТЬ:
В соответствии с запросом, вот мой поток аутентификации:
def get_drive_service(keyfile, user_email):
'''Builds and returns a Drive service object authorized with the service
account that acts on behalf of the given user.
@param keyfile: generated JSON containing the service account details
@param user_email: the email of the user.
@return: Drive API service instance
'''
from oauth2client.service_account import ServiceAccountCredentials
credentials = ServiceAccountCredentials.from_json_keyfile_dict(keyfile, SCOPES)
credentials = credentials.create_delegated(user_email)
http = credentials.authorize(httplib2.Http())
service = discovery.build('drive', 'v3', http=http)
return service
Он основан на OAuth 2.0 между серверами Google. docs (раздел «Другие платформы»), и снова нормально работает при непосредственном вызове функции, а не добавлении ее в очередь задач.