Автоматизация процесса проверки pydrive

Я пытаюсь автоматизировать GoogleAuth процесс при использовании pydrive библиотека ( https://pypi.python.org/pypi/PyDrive).

Я настроил pydrive и Google API таким образом, чтобы мой secret_client.json работает, но для доступа к gdrive требуется веб-аутентификация каждый раз, когда я запускаю свой скрипт:

from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive

gauth = GoogleAuth()
gauth.LocalWebserverAuth()

drive = GoogleDrive(gauth)

textfile = drive.CreateFile()
textfile.SetContentFile('eng.txt')
textfile.Upload()
print textfile

drive.CreateFile({'id':textfile['id']}).GetContentFile('eng-dl.txt')

eng.txt это просто текстовый файл. Более того, когда я пытаюсь использовать вышеуказанный скрипт, когда я вошел в другой аккаунт. Это не загружает eng.txt в мой gdrive, который породил secret_client.json но учетная запись, которая была зарегистрирована, когда я авторизую аутентификацию

Из предыдущего поста я попробовал следующее, чтобы автоматизировать процесс проверки, но он выдает сообщения об ошибках:

import base64, httplib2
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive

from apiclient.discovery import build
from oauth2client.client import SignedJwtAssertionCredentials
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive

#gauth = GoogleAuth()
#gauth.LocalWebserverAuth()

# from google API console - convert private key to base64 or load from file
id = "464269119984-j3oh4aj7pd80mjae2sghnua3thaigugu.apps.googleusercontent.com"
key = base64.b64decode('COaV9QUlO1OdqtjMiUS6xEI8')

credentials = SignedJwtAssertionCredentials(id, key, scope='https://www.googleapis.com/auth/drive')
credentials.authorize(httplib2.Http())

gauth = GoogleAuth()
gauth.credentials = credentials

drive = GoogleDrive(gauth)

drive = GoogleDrive(gauth)

textfile = drive.CreateFile()
textfile.SetContentFile('eng.txt')
textfile.Upload()
print textfile

drive.CreateFile({'id':textfile['id']}).GetContentFile('eng-dl.txt')

Ошибка:

Traceback (most recent call last):
  File "/home/alvas/git/SeedLing/cloudwiki.py", line 29, in <module>
    textfile.Upload()
  File "/usr/local/lib/python2.7/dist-packages/pydrive/files.py", line 216, in Upload
    self._FilesInsert(param=param)
  File "/usr/local/lib/python2.7/dist-packages/pydrive/auth.py", line 53, in _decorated
    self.auth.Authorize()
  File "/usr/local/lib/python2.7/dist-packages/pydrive/auth.py", line 422, in Authorize
    self.service = build('drive', 'v2', http=self.http)
  File "/usr/local/lib/python2.7/dist-packages/oauth2client/util.py", line 132, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/apiclient/discovery.py", line 192, in build
    resp, content = http.request(requested_url)
  File "/usr/local/lib/python2.7/dist-packages/oauth2client/util.py", line 132, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/oauth2client/client.py", line 475, in new_request
    self._refresh(request_orig)
  File "/usr/local/lib/python2.7/dist-packages/oauth2client/client.py", line 653, in _refresh
    self._do_refresh_request(http_request)
  File "/usr/local/lib/python2.7/dist-packages/oauth2client/client.py", line 677, in _do_refresh_request
    body = self._generate_refresh_request_body()
  File "/usr/local/lib/python2.7/dist-packages/oauth2client/client.py", line 861, in _generate_refresh_request_body
    assertion = self._generate_assertion()
  File "/usr/local/lib/python2.7/dist-packages/oauth2client/client.py", line 977, in _generate_assertion
    private_key, self.private_key_password), payload)
  File "/usr/local/lib/python2.7/dist-packages/oauth2client/crypt.py", line 131, in from_string
    pkey = crypto.load_pkcs12(key, password).get_privatekey()
OpenSSL.crypto.Error: [('asn1 encoding routines', 'ASN1_get_object', 'header too long')]

Моя аутентификация на gdrive api выглядит так:

Как я могу использовать pydrive таким образом, чтобы мне не нужно было проходить аутентификацию каждый раз, когда я его использую?

Как разрешить автоматическую аутентификацию таким образом, чтобы скрипт python, использующий скрипт pydrive, загружал только ту учетную запись, которая сгенерировала secret_client.json а не залогинен ли в данный момент аккаунт в интернет браузере?

7 ответов

Решение

Во-первых, вы неправильно понимаете один очень важный момент, как это работает:

когда я пытаюсь использовать вышеуказанный скрипт, когда я вошел в другую учетную запись. Он загружает не eng.txt в мой gdrive, который сгенерировал secret_client.json, а учетную запись, которая была авторизована при авторизации аутентификации

Это именно то, как это должно работать. Вы, как разработчик, распространяете client_secret.json с вашим приложением, и этот файл используется PyDrive для аутентификации приложения в Google. Google хочет знать, сколько запросов API делается каждым приложением по разным причинам (метрика, взимать плату, отзывать доступ и т. Д.), Поэтому оно требует, чтобы приложение аутентифицировалось.

Теперь, когда ваше приложение работает LocalWebserverAuth, это аутентификация клиента с помощью Google. Клиент, конечно, человек, который на самом деле использует ваше приложение. В этом случае разработчик и клиент - это одно и то же лицо (вы), но представьте, что вы хотите распространить свое приложение среди миллионов разных людей. Они должны иметь возможность аутентифицировать себя и загружать файлы в свою учетную запись Drive, вместо того, чтобы все они оказались у вас (разработчика), который предоставил client_secret.json,

Тем не менее, это действительно очень незначительное изменение, чтобы ваше приложение не запрашивало у клиента аутентификацию каждый раз, когда вы запускаете приложение. Вам просто нужно использовать LoadCredentialsFile а также SaveCredentialsFile,

from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive

gauth = GoogleAuth()
# Try to load saved client credentials
gauth.LoadCredentialsFile("mycreds.txt")
if gauth.credentials is None:
    # Authenticate if they're not there
    gauth.LocalWebserverAuth()
elif gauth.access_token_expired:
    # Refresh them if expired
    gauth.Refresh()
else:
    # Initialize the saved creds
    gauth.Authorize()
# Save the current credentials to a file
gauth.SaveCredentialsFile("mycreds.txt")

drive = GoogleDrive(gauth)

textfile = drive.CreateFile()
textfile.SetContentFile('eng.txt')
textfile.Upload()
print textfile

drive.CreateFile({'id':textfile['id']}).GetContentFile('eng-dl.txt')

Альтернативный способ - использовать пользовательский поток авторизации, записав файл setting.yaml в рабочий каталог. И этот метод работает лучше, чем LocalWebserverAuth() сгенерирует токен, срок действия которого истекает всего через один час, и токена обновления нет.

Пример файла settings.yaml выглядит следующим образом

client_config_backend: file
client_config:
    client_id: <your_client_id>
    client_secret: <your_secret>

save_credentials: True
save_credentials_backend: file
save_credentials_file: credentials.json

get_refresh_token: True

oauth_scope:
    - https://www.googleapis.com/auth/drive
    - https://www.googleapis.com/auth/drive.install

С этим файлом вам все равно придется использовать браузер для завершения аутентификации в первый раз, и после этого в рабочем каталоге будет создан файл credentials.json с токеном обновления.

Этот метод работает лучше, если вы пытаетесь автоматизировать ваш скрипт на сервере

Весь этот поток мне очень помог, но после того, как я реализовал все представленные здесь решения, появилась еще одна проблема: LocalWebserverAuth() не получит токен обновления.

Если вы откроете "mycreds.txt", сгенерированный после реализации кода @ dano, вы увидите, что для "токена обновления" будет установлено значение "null". Через пару часов срок действия токена истекает, и вы получаете следующее, и в конечном итоге вам приходится снова вручную проходить аутентификацию.

Ошибка:

raise RefreshError('No refresh_token found.') pydrive.auth.RefreshError: No refresh_token found.Please set access_type of OAuth to offline.

Решение для этого состоит в том, чтобы принудительно установить Appro_promt и отключить access_type для параметров потока GoogleAuth.

Вот как я не получил больше ошибок:

gauth = GoogleAuth()

# Try to load saved client credentials
gauth.LoadCredentialsFile("mycreds.txt")

if gauth.credentials is None:
    # Authenticate if they're not there

    # This is what solved the issues:
    gauth.GetFlow()
    gauth.flow.params.update({'access_type': 'offline'})
    gauth.flow.params.update({'approval_prompt': 'force'})

    gauth.LocalWebserverAuth()

elif gauth.access_token_expired:

    # Refresh them if expired

    gauth.Refresh()
else:

    # Initialize the saved creds

    gauth.Authorize()

# Save the current credentials to a file
gauth.SaveCredentialsFile("mycreds.txt")  

drive = GoogleDrive(gauth)

Спасибо вам всем!

Это просто для завершения поста @wang892 выше (у меня недостаточно репутации, чтобы комментировать).

Этот ответ помог мне автоматизировать мой сценарий (не требуя повторной аутентификации при каждом запуске).

Но поскольку я использовал образец файла settings.yaml, доступный в документации PyDrive, я столкнулся с проблемами (из-за моего полного незнания о том, как работает oauth).

Этот пример файла содержит следующие строки, которые, я думаю, ограничивают мой скрипт PyDrive доступом только к файлам и папкам, созданным им самим (подробности см. В выпуске № 122 PyDrive):

Ограниченный доступ:

oauth_scope:
  - https://www.googleapis.com/auth/drive.file
  - https://www.googleapis.com/auth/drive.install

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

Благодаря этим новым строкам мой скрипт теперь имеет доступ ко всем файлам на моем Google Диске:

Полный доступ:

oauth_scope:
  - https://www.googleapis.com/auth/drive

Немного подробнее об этом в выпуске № 108 PyDrive, который меня очень порадовал.

У меня была аналогичная проблема, и мне не хватало того, что я добавлял себя в качестве тестового пользователя API.

В Google Cloud перейдите в API и службы > Согласие OAuth. Прокрутите вниз, пока не найдете «Тестовый пользователь» и добавьте учетную запись Gmail своего Диска.

Скриншот пользователя Google Cloud Test

Если учетные данные отсутствуют, этот код создает поле ввода с двумя параметрами:

  • Проверка подлинности браузера (что нужно сделать только один раз)

  • Загрузка файла учетных данных (этот файл будет создан в первый раз, когда вы выбираете аутентификацию браузера)

Теперь легко поделиться записной книжкой, которая будет работать без запроса авторизации, поскольку она будет использовать учетные данные, сохраненные в mycreds.txt из локальной среды. Однако, если среда выполнения падает или сбрасывается, этот файл будет утерян, и его нужно будет снова вставить через поле ввода выше. Конечно, вы можете сделать это снова через проверку подлинности браузера, но если вы перераспределяете mycreds.txt людям, использующим ноутбук, они могут использовать функцию Upload для вставки учетных данных в локальную среду.

Последние несколько строк просто предоставляют пример того, как CSV-файл с аутентифицированного диска может быть загружен и использован в записной книжке.

#Install the required packages and fix access to my Google drive account
!pip install pydrive
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
from google.colab import auth
from oauth2client.client import GoogleCredentials


#Checks for file with Google authentication key, if the file is not in place, it asks to authenticate via the browser
gauth = GoogleAuth()
if os.path.isfile("mycreds.txt") is False:
    choice = input ("Do you want to: U) Upload authentication file (mycreds.txt). B) Browser authentication (only possible for owner of the connected Google drive folder). [U/B]? : ")
    if choice == "U":
          print ("Upload the mycreds.txt file")
          from google.colab import files
          files.upload()      
    elif choice == "B":
          auth.authenticate_user()
          gauth.credentials = GoogleCredentials.get_application_default()
          gauth.SaveCredentialsFile("mycreds.txt")

gauth.LoadCredentialsFile("mycreds.txt")
if gauth.access_token_expired:
    gauth.Refresh()
else: gauth.Authorize()

#Now you can easily use the files from your drive by using their ID  
drive = GoogleDrive(gauth)
download = drive.CreateFile({'id': '1KRqYpR9cteX-ZIwhdfghju6_wALl4'})
download.GetContentFile('my_data.csv')
data_frame = pd.read_csv('my_data.csv')

Более гибкая версия, основанная на ответах «дано и тетоденега».

Позволяет вам настроить путь к client_secret.json и mycreds.txt. И это предотвращает истечение срока действия учетных данных в течение 24 часов.

      
    from pydrive2.auth import GoogleAuth
    from pydrive2.drive import GoogleDrive
    from pathlib import Path
    
    gauth = GoogleAuth()
    # optional for custom path of client_secret.json
    # v1-To set a default default in pydrive2
    # gauth.DEFAULT_SETTINGS['client_config_file'] = 'your_path_of_/client_secret.json')
    # v2-To config this for this runtime
    # gauth.settings.update({'client_config_file': 'your_path_of_/client_secret.json'})
    
    mycreds_path = "mycreds.txt file path. Put it in home/.google for security"
    if Path(credentials.mycreds).exists() is False:
        # Authenticate if they're not there
        gauth.DEFAULT_SETTINGS['get_refresh_token'] = True
        gauth.LocalWebserverAuth()
        drive = GoogleDrive(gauth)
        gauth.SaveCredentialsFile(mycreds_path)
    else:
        gauth.LoadCredentialsFile(mycreds_path)
        if gauth.access_token_expired:
            gauth.Refresh()
        else:
            gauth.Authorize()
            drive = GoogleDrive(gauth)

Как работает:
при первом входе в систему требуется подтверждение в браузере.
После первого входа вас больше не будут просить подтверждения в браузере.
Таким образом, будущие входы в систему будут осуществляться с использованием учетных данных из файла mycreds.txt, который хранится в защищенной папке.

Чтобы получить файл client_secret.json, прочтите раздел «Аутентификация» в кратком руководстве по PyDrive2.

Другие вопросы по тегам