Google API Python 的驱动器:如何创建凭据?

Google Drive API for Python: how to create credential?

我正在编写一个 Python 脚本来自动将一些文件上传到 Google 云端硬盘。由于我还是一个 Python 程序员的新手,而且这是一个和其他任何事情一样多的练习,所以我开始关注 Google Quickstart and decided to use their quickstart.py as a basis on which to base my own script. In the part where it talks about how to create credentials for your Python script, it refers to the "Create credentials" link, at https://developers.google.com/workspace/guides/create-credentials

我遵循 link,进入我的一个 Google 云项目,并尝试设置 OAuth 同意屏幕,使用“内部”项目,正如他们告诉您的那样...... .但我不能。 Google 说:

“Because you’re not a Google Workspace user, you can only make your app available to external (general audience) users. ”

所以我尝试创建一个“外部”项目,然后使用桌面应用程序继续创建一个新的客户端 ID。然后我下载 JSON 凭据并将它们放在与我的 Python 脚本相同的文件夹中,如 "credentials.json"。然后我执行 Python 脚本以对其进行身份验证:浏览器打开,我登录到我的 Google 帐户,授予它我的权限......然后浏览器挂起,因为它正在重定向到本地主机URL 显然我的小 Python 脚本根本没有在我的电脑上监听。

我相信他们最近一定改变了这一点,因为一年前我开始遵循相同的 Python 教程并且可以毫无问题地创建凭据,但是 Google Drive API 文档还没有更新。那么...现在如何为 Python 脚本创建凭据?

编辑:在此处添加我的脚本的源代码。正如我所说,它与 Google 的“quickstart.py”非常相似:

from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from googleapiclient.errors import HttpError


# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive.metadata', 'https://www.googleapis.com/auth/drive']



def main():
    """Shows basic usage of the Drive v3 API.
    Prints the names and ids of the first 10 files the user has access to.
    """
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token_myappname.pickle'):
        with open('token_myappname.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token_myappname.pickle', 'wb') as token:
            pickle.dump(creds, token)



    service = build('drive', 'v3', credentials=creds)

    # Call the Drive v3 API
    results = service.files().list(
        pageSize=10, fields="nextPageToken, files(id, name)").execute()
    items = results.get('files', [])


    if not items:
        print('No files found.')
    else:
        #print(items[0])
 
        print('Files:')
        for item in items:
            #print (item)
            print(u'{0}   {1}   {2}'.format(item['name'], item['owners'], item['parents']))
 

我建议您使用服务帐户访问云端硬盘。

为此,您需要与服务帐户电子邮件共享驱动器(或文件夹)。然后使用此代码

from googleapiclient.discovery import build
import google.auth

SCOPES = ['https://www.googleapis.com/auth/drive.metadata', 'https://www.googleapis.com/auth/drive']



def main():
    credentials, project_id = google.auth.default(scopes=SCOPES)


    service = build('drive', 'v3', credentials=credentials)

    # Call the Drive v3 API
    results = service.files().list(
        q=f"'1YJ6gMgACOqVVbcgKviJKtVa5ITgsI1yP' in parents",
        pageSize=10, fields="nextPageToken, files(id, name, owners, parents)").execute()
    items = results.get('files', [])


    if not items:
        print('No files found.')
    else:
        #print(items[0])

        print('Files:')
        for item in items:
            #print (item)
            print(u'{0}   {1}   {2}'.format(item['name'], item['owners'], item['parents']))

如果您 运行 您的代码在 Google 云上,例如在计算引擎实例中,您需要使用您在驱动器中授权的服务帐户自定义 VM。 (不要使用计算引擎默认服务帐户,否则您将需要在您的 VM 上进行额外配置)

如果您 运行 您的脚本在 GCP 之外,您需要生成服务帐户密钥文件并将其存储在本地服务器上。然后,创建一个引用存储密钥文件的完整路径的环境变量 GOOGLE_APPLICATION_CREDENTIALS

除了 Guillaume Blaquiere 编写的另一个解决方案 post 之外,我还自己找到了另一个解决方案,我想将其 post 放在这里以防有帮助。我所要做的就是......呃,实际阅读我正在复制和粘贴的代码,特别是这一行:

creds = flow.run_local_server(port=0)

我在快速入门之外检查了 Google 的文档,发现如下:https://google-auth-oauthlib.readthedocs.io/en/latest/reference/google_auth_oauthlib.flow.html

事实证明,示例代码 在我的计算机中打开一个本地端口来侦听请求,并且可能由于“端口 0”而无法正常工作部分,或其他一些网络问题。

所以我找到的解决方法是使用在文档中找到的不同的身份验证方法:

  creds = flow.run_console()  

在这种情况下,您可以在命令行中手动粘贴 Google 提供给您的授权码。我刚刚试过了,我的凭据很高兴地存储在我的本地 pickle 文件中。