Ich versuche, den GoogleAuth
-Prozess zu automatisieren, wenn Sie die pydrive
-Bibliothek verwenden ( https://pypi.python.org/pypi/PyDrive ).
Ich habe das pydrive und die google API so eingerichtet, dass mein secret_client.json
funktioniert, es erfordert jedoch eine Webauthentifizierung für den Zugriff auf gdrive bei jeder Ausführung meines Skripts:
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
ist nur eine Textdatei. Außerdem, wenn ich versuche, das obige Skript zu verwenden, während ich bei einem anderen Konto angemeldet bin. Es lädt nicht den eng.txt
in mein Laufwerk hoch, der den secret_client.json
generiert hat, sondern das Konto, das bei der Autorisierung der Authentifizierung angemeldet war.
Im vorherigen Beitrag habe ich Folgendes versucht, um den Überprüfungsprozess zu automatisieren, es werden jedoch Fehlermeldungen angezeigt:
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')
Error:
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')]
Meine Authentifizierung auf gdrive api sieht folgendermaßen aus:
Wie kann ich pydrive so verwenden, dass ich mich nicht jedes Mal authentifizieren muss, wenn ich es benutze?
Wie kann eine automatische Authentifizierung zugelassen werden, sodass das Python-Skript, das das Pydrive-Skript verwendet, nur auf das Konto hochgeladen wird, das den secret_client.json
generiert hat, und nicht das aktuell angemeldete Konto im Internetbrowser?
Zuerst missverstehen Sie ein sehr wichtiges Stück, wie das funktioniert:
wenn ich versuche, das obige Skript zu verwenden, während ich bei einem anderen .__ angemeldet bin. Konto. Die eng.txt wird nicht in mein gdrive hochgeladen, das .__ generiert hat. das secret_client.json aber das Konto, das angemeldet war, als ich Autorisieren Sie die Authentifizierung
Genau so soll es funktionieren. Sie als Entwickler verteilen client_secret.json
mit Ihrer Anwendung, und diese Datei wird von PyDrive verwendet, um die Anwendung bei Google zu authentifizieren. Google möchte wissen, wie viele API-Anforderungen jede Anwendung aus verschiedenen Gründen anfordert (Metriken, Belastung des Kontos, Zugriff widerrufen usw.). Daher muss sich die Anwendung authentifizieren.
Wenn Ihre Anwendung LocalWebserverAuth
ausführt, wird der client jetzt bei Google authentifiziert. Der Kunde ist natürlich die Person, die Ihre Anwendung tatsächlich verwendet. In diesem Fall sind der Entwickler und der Kunde dieselbe Person (Sie). Sie können sich jedoch vorstellen, dass Sie Ihre Anwendung an eine Million verschiedene Personen verteilen möchten. Sie müssen in der Lage sein, sich zu authentifizieren und Dateien in ihr eigenes Drive-Konto hochzuladen, anstatt sie alle in Ihrem (dem Entwickler) zu enden, der client_secret.json
angegeben hat.
Das heißt, es ist wirklich nur eine sehr geringfügige Änderung, um es so zu machen, dass Ihre App den Client nicht bei jeder Ausführung der App zur Authentifizierung auffordern muss. Sie müssen nur LoadCredentialsFile
und SaveCredentialsFile
verwenden.
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')
Alternativ können Sie einen benutzerdefinierten Authentifizierungsfluss verwenden, indem Sie die Datei setting.yaml in das Arbeitsverzeichnis schreiben. Und diese Methode funktioniert besser, da LocalWebserverAuth()
ein Token generiert, das in nur einer Stunde abläuft und es kein Aktualisierungstoken gibt.
Ein Beispiel für die Datei settings.yaml sieht folgendermaßen aus
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
Bei dieser Datei müssen Sie noch einen Browser verwenden, um die Authentifizierung zum ersten Mal abzuschließen, und anschließend wird eine credentials.json-Datei mit einem Aktualisierungstoken im Arbeitsverzeichnis generiert.
Diese Methode funktioniert besser, wenn Sie versuchen, Ihr Skript auf dem Server zu automatisieren
Dieser ganze Thread hat mir sehr geholfen, aber nachdem ich alle hier vorgestellten Lösungen implementiert hatte, trat ein weiteres Problem auf: LocalWebserverAuth () wird das Aktualisierungstoken nicht erhalten.
Wenn Sie die "mycreds.txt" öffnen, die nach der Implementierung von @ dano generiert wurde, wird das "Aktualisierungstoken" auf "null" gesetzt. Nach ein paar Stunden verfällt das Token und Sie erhalten Folgendes und müssen sich am Ende erneut manuell authentifizieren.
Der Fehler:
raise RefreshError('No refresh_token found.') pydrive.auth.RefreshError: No refresh_token found.Please set access_type of OAuth to offline.
Die Lösung hierfür besteht darin, die Eingabeaufforderung "approved_promt" zu erzwingen und "access_type" in den Ablaufparametern von GoogleAuth auf "offline" zu setzen.
So habe ich keine Fehler mehr bekommen:
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)
Danke euch allen!
Wenn die Anmeldeinformationen nicht vorhanden sind, generiert dieser Code ein Eingabefeld mit zwei Optionen:
Browser-Authentifizierung (die Sie nur einmal durchführen müssen)
Upload der Berechtigungsnachweisdatei (diese Datei wird zu der ersten Zeit generiert, die Sie für die Browser-Authentifizierung ausgewählt haben)
Nun ist es einfach, das Notebook gemeinsam zu nutzen, das einfach ohne Autorisierung ausgeführt werden kann, da es die in der mycreds.txt gespeicherten Anmeldeinformationen der lokalen Umgebung verwendet. Wenn die Laufzeit jedoch abstürzt oder zurückgesetzt wird, geht diese Datei verloren und muss erneut über das Eingabefeld oben eingefügt werden. Natürlich können Sie dies erneut über die Browser-Authentifizierung tun. Wenn Sie mycreds.txt jedoch an die Benutzer des Notebooks verteilen, können diese die Berechtigungsnachweise verwenden, um die Anmeldeinformationen in die lokale Umgebung einzufügen.
Die letzten Zeilen enthalten nur ein Beispiel dafür, wie eine CSV-Datei vom authentifizierten Laufwerk hochgeladen und im Notebook verwendet werden kann.
#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')
Dies ist nur zum Abschluss von @ wang892 Beitrag oben (Ich habe nicht genug Ruf, um einen Kommentar abzugeben).
Diese Antwort hat mir dabei geholfen, mein Skript zu automatisieren (nicht bei jeder Ausführung erneut authentifizieren zu müssen).
Als ich jedoch die Beispieleinstell.yaml-Datei verfügbar in PyDrive-Dokumentation verwendet habe, bin ich auf Probleme gestoßen (aufgrund meiner völligen Unkenntnis darüber, wie Oauth funktioniert).
Diese Beispieldatei enthält diese Zeilen, die meines Erachtens mein PyDrive-Skript auf den Zugriff auf nur von ihnen selbst erstellte Dateien und Ordner beschränkten (siehe PyDrive-Problem # 122 für Details):
Eingeschränkter Zugang:
oauth_scope:
- https://www.googleapis.com/auth/drive.file
- https://www.googleapis.com/auth/drive.install
Als ich diese Zeilen änderte, war das Problem gelöst (ich musste meine gespeicherten Anmeldeinformationen entfernen und das Skript ausführen, um es erneut zu autorisieren, nur noch einmal).
Mit diesen neuen Zeilen hat mein Skript nun Zugriff auf alle Dateien in meinem Google Drive:
Voller Zugriff:
oauth_scope:
- https://www.googleapis.com/auth/drive
Ein wenig mehr dazu in PyDrive Ausgabe # 108 , was mich sehr beleuchtet hat.