简体   繁体   English

自动化 pydrive 验证过程

[英]Automating pydrive verification process

I am trying to automate the GoogleAuth process when using the pydrive library ( https://pypi.python.org/pypi/PyDrive ).我正在尝试在使用pydrive库( https://pypi.python.org/pypi/PyDrive )时自动化GoogleAuth过程。

I've set up the pydrive and the google API such that my secret_client.json works but it requires web authentication for gdrive access every time i run my script:我已经设置了 pydrive 和 google API 以便我的secret_client.json工作,但每次我运行我的脚本时它都需要 web 身份验证来访问 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 is just a textfile. eng.txt只是一个文本文件。 Moreover when I try to use the above script while I am logged into another account.此外,当我在登录另一个帐户时尝试使用上述脚本时。 It doesn't upload the eng.txt into my gdrive that generated the secret_client.json but the account that was logged in when I authorize the authentication它不会将eng.txt上传到生成secret_client.json的 gdrive 中,而是在我授权身份验证时登录的帐户

From the previous post, I've tried the following to automate the verification process but it's giving error messages:在上一篇文章中,我尝试了以下方法来自动化验证过程,但它给出了错误消息:

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')]

My authentication on gdrive api looks like this:我在 gdrive api 上的身份验证如下所示:

在此处输入图像描述

How could I use pydrive such that I do not need to authenticate everytime I use it?我怎样才能使用 pydrive,这样我每次使用它时都不需要进行身份验证?

How to allow automatic authentication such that the python script using the pydrive script will only upload to the account that generated the secret_client.json and not the currently logged on account on the internet browser?如何允许自动身份验证,以便使用 pydrive 脚本的 python 脚本只会上传到生成secret_client.json的帐户,而不是当前在 Internet 浏览器上登录的帐户?

First, you're misunderstanding one very important bit of how this works:首先,您误解了其工作原理的一个非常重要的部分:

when I try to use the above script while I am logged into another account.当我在登录另一个帐户时尝试使用上述脚本时。 It doesn't upload the eng.txt into my gdrive that generated the secret_client.json but the account that was logged in when I authorize the authentication它不会将 eng.txt 上传到我生成 secret_client.json 的 gdrive 中,而是将我授权身份验证时登录的帐户

This is exactly how it's supposed to work.这正是它应该如何工作的。 You, as the developer, distribute client_secret.json with your application, and that file is used by PyDrive to authenticate the application with Google.作为开发人员,您将client_secret.json与您的应用程序一起分发,PyDrive 使用该文件向 Google 验证应用程序 Google wants to know how many API requests are being made by each application out there for all sorts of reasons (metrics, charge the account, revoke access, etc.), so it requires the application to authenticate itself. Google 想知道由于各种原因(指标、对帐户收费、撤销访问等),每个应用程序发出了多少 API 请求,因此它要求应用程序对自身进行身份验证。

Now, when your application runs LocalWebserverAuth , it's authenticating the client with Google.现在,当您的应用程序运行LocalWebserverAuth ,它正在向 Google 验证客户端 The client, of course, is the person actually using your application.客户当然是实际使用您的应用程序的人。 In this case, the developer and client are the same person (you), but imagine your want to distribute your application to a million different people.在这种情况下,开发人员和客户是同一个人(您),但是想象一下您想将您的应用程序分发给一百万个不同的人。 They need to be able to authenticate themselves and upload files to their own Drive account, rather that having them all end up in yours (the developer), who provided client_secret.json .他们需要能够对自己进行身份验证并将文件上传到他们自己的 Drive 帐户,而不是让它们最终都在您(开发人员)的帐户中,他们提供了client_secret.json

That said, it's really just a very minor change to make it so your app doesn't have to ask the client to authenticate every time you run the app.也就是说,这实际上只是一个非常小的更改,因此您的应用程序不必在每次运行应用程序时都要求客户端进行身份验证。 You just need to use LoadCredentialsFile and SaveCredentialsFile .您只需要使用LoadCredentialsFileSaveCredentialsFile

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')

An alternative way is to use a custom auth flow by writing a setting.yaml file into the working directory.另一种方法是通过将 setting.yaml 文件写入工作目录来使用自定义身份验证流程。 And this method works better as LocalWebserverAuth() will generate a token that expires in just one hour and there is no refresh token.这种方法效果更好,因为LocalWebserverAuth()将生成一个仅在一小时内到期的令牌,并且没有刷新令牌。

A sample settings.yaml file looks like this示例 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

With this file, you still have to use a browser to complete authentication for the first time, and after that a credentials.json file will be generated in the working directory with a refresh token.有了这个文件,第一次还是要使用浏览器来完成认证,之后会在工作目录下生成一个带有refresh token的credentials.json文件。

This method works better if you are trying to automate your script on server如果您尝试在服务器上自动化脚本,则此方法效果更好

This whole thread helped me a lot, but after I implemented all the solutions presented here one more issue came along: LocalWebserverAuth() won't get the refresh token .整个线程对我帮助很大,但是在我实施了此处介绍的所有解决方案后,又出现了一个问题:LocalWebserverAuth() 将不会获得刷新令牌

If you open the "mycreds.txt" generated after you implement @dano's code, you'll see that the "refresh token" will be set to "null".如果您打开实现@dano 代码后生成的“mycreds.txt”,您会看到“刷新令牌”将被设置为“空”。 After a couple of hours, the token expires and you get the following and end up having to manually authenticate again.几个小时后,令牌过期,您将获得以下信息,最终不得不再次手动进行身份验证。

The error:错误:

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

The solution for that is to force the approval_promt and set access_type to offline on the flow params of the GoogleAuth.解决方案是在 GoogleAuth 的流参数上强制批准_​​promt 并将 access_type 设置为离线。

Here's how I got no more errors:这是我没有更多错误的方法:

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)

Thank you all!谢谢你们!

This is just to complete @wang892 post above (I have not enough reputation to comment).这只是为了完成上面的@wang892帖子(我没有足够的声誉来评论)。

That answer helped me to automate my script (not having to reauthenticate each time I run it).该答案帮助我自动化了我的脚本(不必每次运行时都重新进行身份验证)。

But as I used the sample settings.yaml file available in PyDrive documentation , I ran into problems (due to my complete ignorance about how oauth works).但是当我使用PyDrive 文档中提供的示例 settings.yaml 文件时,我遇到了问题(由于我完全不了解 oauth 的工作原理)。

That sample file contains these lines, which I think were limiting my PyDrive script to access only to files and folders created by itself (see PyDrive issue #122 for details):该示例文件包含这些行,我认为这些行限制了我的 PyDrive 脚本只能访问自己创建的文件和文件夹(有关详细信息,请参阅PyDrive 问题 #122 ):

Limited access:访问受限:

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

When I changed those lines the problem was solved (I had to remove my stored credentials and ran the script to reauthorise it, just once again).当我更改这些行时,问题就解决了(我必须再次删除我存储的凭据并运行脚本以重新授权它)。

With these new lines my script has now access to all files in my Google Drive:通过这些新行,我的脚本现在可以访问我的 Google Drive 中的所有文件:

Full access:完全访问:

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

A bit more about this in PyDrive issue #108 , which enlighted me a lot.PyDrive issue #108 中有更多关于这个的信息,这让我很受启发

If the credentials are not in place, this code generates an input box with two options:如果凭据没有到位,此代码会生成一个带有两个选项的输入框:

  • Browser authentication(which you need to do just once)浏览器身份验证(您只需要做一次)

  • Upload of the credentials file (this file will be generated the fist time you choose for Browser authentication上传凭证文件(此文件将在您第一次选择浏览器身份验证时生成

Now it is easy to share the notebook, which will just run without asking for authorization, since it will be using the credentials saved in the mycreds.txt from the local environment.现在可以轻松共享笔记本,该笔记本无需授权即可运行,因为它将使用本地环境中 mycreds.txt 中保存的凭据。 However, if the runtime crashes or is reset, that file will be lost and it need to be inserted again via the input box above.但是,如果运行时崩溃或重置,该文件将丢失,需要通过上面的输入框再次插入。 Of course you can do this again via the Browser authentication, but if you redistribute the mycreds.txt to the people that are using the notebook, they can use the Upload function to insert the credentials to the local environment.当然,您可以通过浏览器身份验证再次执行此操作,但是如果您将 mycreds.txt 重新分发给使用笔记本的人,他们可以使用上传功能将凭据插入到本地环境中。

The final few lines just provide an example of how a csv file from the authenticated drive can be uploaded and used in the notebook.最后几行仅提供了一个示例,说明如何将经过身份验证的驱动器中的 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')

I was having a similar issue, and the bit that I was missing was adding myself as the test user of the API.我遇到了类似的问题,我缺少的一点是将自己添加为 API 的测试用户。

In Google Cloud, go to APIs & Services > OAuth consent.在 Google Cloud 中,go 同意 API 和服务 > OAuth。 Scroll down until you find Test User and add the Gmail account of your Drive.向下滚动直到找到测试用户并添加驱动器的 Gmail 帐户。

Google Cloud Test User Screenshot谷歌云测试用户截图

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 PyDrive和Google Drive - 自动化验证流程? - PyDrive and Google Drive - automate verification process? 在Windows中自动化进程 - Automating a process in windows 自动化正则表达式以处理多个文件 - automating regex to process multiple files 自动化 Python package 发布过程 - Automating Python package release process 在Selenium Python中自动搜索过程中没有错误但没有输出 - No error but no output for in automating search process in selenium python 关于自动化 Sharepoint 工作流以处理 Excel 文件的建议 - Suggestions on automating Sharepoint workflows to process Excel Files 使用GAE python实施电子邮件验证流程 - Implementing Email Verification process with GAE python 有没有一种方法可以自动为 Selenium 项目下载最新的 Chrome 驱动程序? - Is there a method of automating the process of downloading the latest Chrome Driver for a Selenium project? 自动识别 pandas dataframe 的子组,这些子组的值没有显着差异 - Automating the process of identifying subgroups of a pandas dataframe that do not significantly differ on a value Buildroot 中的 Python - PyDrive 错误 - Python in Buildroot - PyDrive errors
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM