GSpread 通行证来自 Python 而不是 JSON

GSpread pass credentials from Python not JSON

我正在使用 GSpread 尝试将我的 JSON 文件中的内容(Google API 服务应用程序凭据)作为脚本中的 python 字典传递。我尽量不随身携带 json 文件。

当我尝试在以下行中传递字典而不是 json 文件时出现以下错误:

credentials = ServiceAccountCredentials.from_json_keyfile_name(auth_gdrive(), scope)

TypeError:应为 str、bytes 或 os.PathLike 对象,未设置

### auth_gdrive() returns a dictionary like this:

def auth_gdrive():
    dic = {
        "type": "miauuuuuu",
        "pass": "miauuuu"
    }

我不允许显示 dic 中的真实内容。

由于您正在使用 ServiceAccountCredentials,我假设您正在使用 OAuth2 进行授权。您可以通过使用 oauth2client.SignedJwtAssertionCredentials 创建适当的凭据对象并将其传递给 gspread.authorize.

来跳过 json 文件
import gspread
from oauth2client.client import SignedJwtAssertionCredentials

credentials = SignedJwtAssertionCredentials(service_account_name, private_key.encode(), 
                                            ['https://spreadsheets.google.com/feeds'])
gclient = gspread.authorize(credentials)

更新:oauth2client.SignedJwtAssertionCredentials 似乎已被弃用,取而代之的是 oauth2client.service_account.ServiceAccountCredentials,后者仅支持 json 和 p12 密钥文件。

因为我想从我的应用程序中传递凭据详细信息,而不是从 json 文件中传递,所以我无法使用:

ServiceAccountCredentials.from_json_keyfile_name()

from_json_keyfile_name() 需要一个 json 文件。但是查看文档我发现了以下内容:

ServiceAccountCredentials.from_json_keyfile_dict()

这需要一个字典对象,这就是我所需要的。

Link:

https://oauth2client.readthedocs.io/en/latest/source/oauth2client.service_account.html

再次感谢大家

附加提示:我正在使用 Google API 读取 Google 驱动器文件,但也使用 AWS。我将服务账户凭证存储在 AWS Secrets Manager 中,因此我不需要文件。我 copy-pasted 每个 key-value 对从下载的 JSON 文件到 AWS Secrets Manager。但我一直收到错误消息:

Traceback (most recent call last):
  File "./copy_from_google_drive_to_s3.py", line 301, in <module>
    sys.exit(main())
  File "./copy_from_google_drive_to_s3.py", line 96, in main
    keyfile_dict=keyDict, scopes=scopes,
  File "/usr/local/lib/python3.7/site-packages/oauth2client/service_account.py", line 253, in from_json_keyfile_dict
    revoke_uri=revoke_uri)
  File "/usr/local/lib/python3.7/site-packages/oauth2client/service_account.py", line 185, in _from_parsed_json_keyfile
    signer = crypt.Signer.from_string(private_key_pkcs8_pem)
  File "/usr/local/lib/python3.7/site-packages/oauth2client/_pure_python_crypt.py", line 182, in from_string
    raise ValueError('No key could be detected.')
ValueError: No key could be detected.

我必须将换行符的字符串表示形式转换回换行符:

# Last part of using AWS Secrets Manager, returns json string.
sa_creds = get_secret_value_response['SecretString']
# Convert JSON string to dict.
sa_creds = json.loads(sa_creds)
# In the private key, 1-char newline got replaced with 2-char '\n'
sa_creds['private_key'] = sa_creds['private_key'].replace('\n', '\n')
credentials = ServiceAccountCredentials.from_json_keyfile_dict(
    keyfile_dict=sa_creds,
    scopes=['https://www.googleapis.com/auth/drive.readonly',]
)

我的解决方案接近 Bob McCormick。不同之处在于它使用凭据方法来使用服务帐户信息而不是 JSON 文件。

我在这里使用 Google 的 Secret Manager 导入服务帐户信息,以便我的代码可以连接到不同的 GCP 项目:

from google.cloud import secretmanager
from google.oauth2 import service_account

# Create the Secret Manager client.
secret_client = secretmanager.SecretManagerServiceClient()
    
# Build the resource name of the secret version.
name = f"projects/{project-id}/secrets/{very-secret-secret-name}/versions/latest"
    
# Access the secret version.
secret_response = secret_client.access_secret_version(request={"name": name})
    
# Getting the secret data                                                               
secret_payload = json.loads(secret_response.payload.data.decode("UTF-8"))
    
# Applying the credentials as INFO instead of JSON
credentials = service_account.Credentials.from_service_account_info(
                secret_payload,
                scopes=["https://www.googleapis.com/auth/cloud-platform"],
               )