【问题标题】:How to expose Gmail API credentials.json to env如何将 Gmail API credentials.json 暴露给 env
【发布时间】:2020-09-05 05:08:23
【问题描述】:

我正在使用 google gmail api 库在 python 中编写一个 gmail 数据查询项目,并且我正在使用 Gmail API credentials.json 文件。

如何将我的凭据存储在私有环境中,这样当其他人使用我的脚本时,他们就不会自动使用我的 gmail credentials.json。

这是我尝试过的。 在我的 .env 文件中,我创建了一个变量 CRED

CRED={"installed":{"client_id":"##########-#########.apps.googleusercontent.com","project_id":"email-query-#######","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"#############################","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}}

之后,我写了如下代码:

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

def main():

    creds = None

    if os.path.exists('token.pickle'):
        with open('token.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:

            config = json.loads(os.environ['CRED']) 
            flow = InstalledAppFlow.from_client_config(config, SCOPES)
            creds = flow.run_local_server(port=0)
        #Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    http = httplib2.Http()
    http = creds.authorize(http)
    service = build('gmail', 'v1', http=http) #  
    # Call the Gmail API to fetch INBOX
    results = service.users().messages().list(userId='me',labelIds = ['INBOX']).execute()
    messages = results.get('messages', [])

运行代码后,出现以下错误:

<ipython-input-16-d58887cf8862> in <module>
    106 
    107 if __name__ == '__main__':
--> 108     main()

<ipython-input-16-d58887cf8862> in main()
     15             #creds = flow.run_local_server(port=0)
     16 
---> 17             config = json.loads(os.environ['CRED'])
     18             flow = InstalledAppFlow.from_client_config(config, SCOPES)
     19             creds = flow.run_local_server(port=0)

~/anaconda3/lib/python3.7/os.py in __getitem__(self, key)
    677         except KeyError:
    678             # raise KeyError with the original key value
--> 679             raise KeyError(key) from None
    680         return self.decodevalue(value)
    681 

KeyError: 'CRED'

我还要指出,在运行代码之前,我从工作目录中删除了 credentials.json。

还有一件事,如果我将 credentials.json 文件留在工作目录中并运行脚本,我会收到错误消息:

 23 
     24     http = httplib2.Http()
---> 25     http = creds.authorize(http)
     26     service = build('gmail', 'v1', http=http) #
     27     # Call the Gmail API to fetch INBOX

AttributeError: 'Credentials' object has no attribute 'authorize'

我该怎么办?

【问题讨论】:

  • 你把代码推送到github了吗?
  • “env”是什么意思?
  • 如何使用json.dumps 到您的credentials.json 作为环境变量中的字符串,并加载json.loads 以加载凭据。
  • 你尝试或研究了什么?
  • 谢谢。有效。 @PenutChen

标签: python gmail-api google-api-python-client


【解决方案1】:

我建议您的credentials.json 来自Python Quickstart Gamil API,我将本教程用作示例代码。推荐你使用pipenv,环境配置不会太复杂。

首先你需要安装你的虚拟环境:

pip install pipenv
pipenv install google-api-python-client google-auth-httplib2 google-auth-oauthlib

如果你不喜欢使用pipenv或者你不知道如何配置虚拟环境,你可以安装dotenv包:

pip install python-dotenv

然后将这些添加到代码的头部:

from dotenv import load_dotenv;
load_dotenv()

在文件夹的根目录下添加一个名为 .env 的文件:

CRED="Whole JSON String in credentials.json"

当您从pipenv run python script.py 运行您的python 文件时,.env 文件中的环境变量将被加载。

加载credentials.json的原始代码块:

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)

应该修改为:

if not creds or not creds.valid:
    if creds and creds.expired and creds.refresh_token:
        creds.refresh(Request())
    else:
        config = json.loads(os.environ['CRED'])
        flow = InstalledAppFlow.from_client_config(
            config, SCOPES)
        creds = flow.run_local_server(port=0)

通过pipenv run python script.py运行你的程序,你会看到一个提示Loading .env environment variables…

如果您使用版本控制,可以将.env 添加到.gitignore,并添加一个名为.env.template 的文件,其中只留下一个CRED=

更多细节可以阅读pipenvGoogle authlib的文档。

【讨论】:

  • 抱歉,credentials.json 文件中的整个 json 字符串是什么意思?
  • 如果你按照Python Quickstart Gamil API的步骤,你会得到一个名为credential.json的文件。打开该文件,复制所有文本并粘贴到TOKEN= 后面。
  • 17 config = json.loads(os.environ['CRED']) 18 flow = InstalledAppFlow.from_client_config(config, SCOPES) 19 creds = flow.run_local_server(port=0) ~/anaconda3/ lib/python3.7/os.py in __getitem__(self, key) 677 except KeyError: 678 # raise KeyError with the original key value --> 679 raise KeyError(key) from None 680 return self.decodevalue(value) 681 KeyError :“信用”
  • 我将 credentials.json 内容复制到 .env 文件中的 CRED。再次运行脚本后,我得到了 KeyError: 'CRED' 作为错误。
  • 我已经用完整的代码及其显示的错误重新编辑了我的问题。 @PenutChen
【解决方案2】:

您可以使用os.getenv('GMAIL_API'),假设您的环境中已经有“GMAIL_API”变量。

以下是为每个环境添加变量的方法:

对于windows,你可以使用this

对于 Linux,您可以使用 this

【讨论】:

  • 如何定义我的 GMAIL_API 变量?
  • 我该如何实现?我有一个 credentials.json 文件。我需要一个线索。 @亚当谢里夫。
猜你喜欢
  • 2023-03-08
  • 1970-01-01
  • 2011-09-14
  • 1970-01-01
  • 2011-09-07
  • 1970-01-01
  • 2015-10-26
  • 2017-01-06
  • 2012-12-21
相关资源
最近更新 更多