【问题标题】:Setting GOOGLE_APPLICATION_CREDENTIALS for BigQuery Python CLI为 BigQuery Python CLI 设置 GOOGLE_APPLICATION_CREDENTIALS
【发布时间】:2016-05-11 15:24:00
【问题描述】:

我正在尝试使用 Python 通过 BigQuery API 连接到 Google BigQuery。

我在这里关注这个页面: https://cloud.google.com/bigquery/bigquery-api-quickstart

我的代码如下:

import os
import argparse

from apiclient.discovery import build
from apiclient.errors import HttpError
from oauth2client.client import GoogleCredentials

GOOGLE_APPLICATION_CREDENTIALS = './Peepl-cb1dac99bdc0.json'

def main(project_id):
    # Grab the application's default credentials from the environment.
    credentials = GoogleCredentials.get_application_default()
    print(credentials)
    # Construct the service object for interacting with the BigQuery API.
    bigquery_service = build('bigquery', 'v2', credentials=credentials)

    try:
        query_request = bigquery_service.jobs()
        query_data = {
            'query': (
                'SELECT TOP(corpus, 10) as title, '
                'COUNT(*) as unique_words '
                'FROM [publicdata:samples.shakespeare];')
        }

        query_response = query_request.query(
            projectId=project_id,
            body=query_data).execute()

        print('Query Results:')
        for row in query_response['rows']:
            print('\t'.join(field['v'] for field in row['f']))

    except HttpError as err:
        print('Error: {}'.format(err.content))
        raise err


if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('project_id', help='Your Google Cloud Project ID.')

    args = parser.parse_args()

    main(args.project_id)

但是,当我通过终端运行此代码时,出现以下错误:

oauth2client.client.ApplicationDefaultCredentialsError: The Application Default Credentials are not available. They are available if running in Google Compute Engine. Otherwise, the environment variable GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.

正如您在代码中看到的,我尝试根据错误中的链接设置GOOGLE_APPLICATION_CREDENTIALS。但是,错误仍然存​​在。有谁知道问题是什么?

提前谢谢你。

【问题讨论】:

  • 所有这些解决方案都依赖于服务器上可用的凭证 JSON 文件,这是不可取的。我真的希望 Google/GCP 能够接受环境变量。

标签: python google-bigquery


【解决方案1】:

错误消息中提供的链接https://developers.google.com/identity/protocols/application-default-credentials 表示将环境变量 设置为指向包含JSON 服务凭据的失败。看起来你设置了一个 Python 变量。尝试将终端的环境变量设置为指向正确的文件。

当您不在 GCE 容器中运行时,另一种方法是显式使用其他一些凭据,例如 oauth2client.client.SignedJwtAssertionCredentials,并将其直接指向您的客户端密码,这样您就不必通过环境变量进行间接访问。

【讨论】:

    【解决方案2】:

    它在本地 UNIX(或其他)环境中寻找环境变量,而不是 Python 脚本中的变量。

    您可以通过打开终端或 cygwin 并执行以下操作之一来设置:

    export GOOGLE_APPLICATION_CREDENTIALS='/path/to/your/client_secret.json'
    

    在您的终端中键入该变量以设置此会话的变量

    在 UNIX 中通过键入 nano ~/.bashrc 打开您的 .bashrc 文件,如果您看到该标题,请将此行添加到用户特定别名下方:

    GOOGLE_APPLICATION_CREDENTIALS="/full/path/to/your/client_secret.json"
    

    然后通过键入 source ~/.bashrc 重新加载它并通过尝试echo $GOOGLE_APPLICATION_CREDENTIALS 确认它已设置。如果它返回路径,你很好。

    【讨论】:

    【解决方案3】:

    它正在寻找环境变量。但是我能够通过使用应用程序默认凭据在 Windows 平台上解决这个问题。

    我遵循的步骤:

    • 已安装 Google SDK
    • 然后执行gcloud init 步骤来指定我的默认凭据和默认项目,您可以在需要时更改它们。 gcloud 可执行文件可以在您选择安装 Google SDK 的 bin 目录中找到。
    • 成功提供凭证后,您可以在C:\Users\"yourusername"\AppData\Roaming\gcloud\legacy_credentials\"youremail"位置签到 .您可以在那里找到以 JSON 格式存储的凭据。

    它帮助我解决了错误。

    【讨论】:

      【解决方案4】:

      首先 - 感谢您的代码 - 这非常有用。 我还建议直接在您的代码中添加设置环境变量 - 因为不要为您工作的每个环境都设置它。 您可以使用以下代码:

      import os
      os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "path_to_your_.json_credential_file"
      

      我发现这在需要不同凭据的不同项目之间切换时很有用。

      【讨论】:

      • 嗨,我把这行放在哪里以使用具有不同帐户的 google api?谢谢
      • “import os”在代码开头只需要一次。每次在帐户之间切换之前更改“os.environ”。将路径更改为帐户的路径。
      • 非常感谢。对于新手,如果您使用 django,请在 django-project 设置文件中添加代码 import os os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "path_to_your_.json_credential_file"
      【解决方案5】:

      如果您想在不设置环境变量的情况下使用不同的凭证文件,可以使用以下代码:

      from oauth2client import service_account
      from apiclient.discovery import build
      import json
      
      client_credentials = json.load(open("<path to .json credentials>"))
      
      credentials_token = service_account._JWTAccessCredentials.from_json_keyfile_dict(client_credentials)
      
      bigquery_service = build('bigquery', 'v2', credentials=credentials_token)
      query_request = bigquery_service.jobs()
      query_data = {
          'query': (
                  'SELECT TOP(corpus, 10) as title, '
                  'COUNT(*) as unique_words '
                  'FROM [publicdata:samples.shakespeare];')
          }
      
      query_response = query_request.query(
                 projectId=project_id,
                 body=query_data).execute()
      
      print('Query Results:')
      for row in query_response['rows']:
          print('\t'.join(field['v'] for field in row['f']))
      

      【讨论】:

        【解决方案6】:

        我不确定BigQuery,但我使用Google Data Store 进行保存。如果你已经在你的mac中安装了gcloud sdk,你可以尝试运行这个命令

        gcloud auth application-default login
        

        【讨论】:

        • 这正是我想要的。每当我尝试使用默认实例 (BigQueryOptions.getDefaultInstance().getService()) 查询任何内容 (bigquery) 时,我都会收到 401...只需对“应用程序默认”进行身份验证,它就可以正常工作了。谢谢。
        • 谢谢!我花了很多时间试图弄清楚如何让默认凭据与服务帐户一起使用,这正是我想要的。
        • 是否在某处记录了该登录的特定用例?
        • 我不记得我是从哪里得到这个的 :( 。但在这里找到了文档 cloud.google.com/sdk/gcloud/reference/auth/application-default/…
        • 对于那些想要在不将 dev pc 特定文件放入其代码中的情况下进行编码的人来说,这是最佳答案。例如,如果您正在为 Cloud Functions 编码 - 不需要手动 json 文件条目。使编码更接近那种环境。
        【解决方案7】:

        GOOGLE_APPLICATION_CREDENTIALS 未找到 C# 的错误解决方案

        System.Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS",@"C:\apikey.json");
        string Pathsave = System.Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS");
        

        【讨论】:

          【解决方案8】:

          注意:oauth2client is deprecated,而不是GoogleCredentials.get_application_default(),您可以使用google.auth.default()。首先安装软件包:

          pip install google-auth
          

          在您的具体示例中,我看到您从代码中知道 JSON 文件的位置。您可以使用 use a service account directly 模块代替默认凭据(来自环境变量)。

          credentials = google.oauth2.service_account.Credentials.from_service_account_file(
              './Peepl-cb1dac99bdc0.json',
              scopes=['https://www.googleapis.com/auth/cloud-platform'])
          

          您可以像当前一样使用此凭据文件,方法是将它们传递给googleapiclient.discovery.build,或者如果您使用的是google-cloud-bigquery library,则将凭据传递给google.cloud.bigquery.Client 构造函数。

          【讨论】:

            【解决方案9】:

            您可以使用from_service_account_json() 创建具有服务帐户凭据的客户端:

            from google.cloud import bigquery
            bigqueryClient = bigquery.Client.from_service_account_json('/path/to/keyfile.json')
            

            【讨论】:

              【解决方案10】:

              在您的项目文件夹中输入:

              set GOOGLE_APPLICATION_CREDENTIALS='\path\key.json'
              

              【讨论】:

                【解决方案11】:
                • 从命令行导出 Google 凭据 JSON:
                  export GOOGLE_APPLICATION_CREDENTIALS='\path\key.json'
                  我希望它能正常工作。

                【讨论】:

                  【解决方案12】:

                  如果存在无法在文件集中提供凭据的情况 GOOGLE_APPLICATION_CREDENTIALS='\path\key.json'

                  1. 由于服务帐号为 JSON 且包含双引号字符,请将每个双引号替换为 \"
                  2. 将完整的 JSON 用双引号括起来
                  3. 将每个 \n 替换为 \\n(在 linux 上)\\\n(在 mac)

                  如果您将其导出为变量,则服务帐户的上述更改应正确记录。

                  尝试echo %variable_name 确认它是否看起来不错。

                  【讨论】:

                    【解决方案13】:

                    除了使用GOOGLE_APPLICATION_CREDENTIALS(已经在一堆答案中描述)之外,还有另一种方法可以将生成的 json 凭据设置为默认服务帐户:

                    gcloud auth activate-service-account --key-file=<path to your generated json file>
                    

                    这将激活一个默认帐户(并根据提供的json文件设置凭据)而不显式设置GOOGLE_APPLICATION_CREDENTIALS,并且在重新登录或重新启动后仍然会被激活而不修改.bashrc。

                    【讨论】:

                      【解决方案14】:

                      我认为这里还没有提到另一种解决方法。 google.oauth2.service_account.Credentials 对象提供了 from_service_account_info 方法(参见此处:https://github.com/googleapis/google-auth-library-python/blob/main/google/oauth2/service_account.py)。

                      所以你可以在你的环境中设置任何你想要的变量并将其读入并将其传递给函数,如下所示:

                      your_data = { 
                      "type": os.environ.get('YOUR_ENV_VAR'),
                      "project_id": os.environ.get('YOUR_ENV_VAR'),
                      "private_key_id": os.environ.get('YOUR_ENV_VAR'),
                      #... and so on with all the required Google variables....
                      }
                      your_credentials = service_account.Credentials.from_service_account_info(your_data, scopes=your_scopes)
                      service = discovery.build(api_name, api_version, credentials=your_credentials)
                      

                      我基本上从我的 google keyfile.json 中获取了所有数据并将它们存储在 env 中并执行了上述操作。这样你就不需要把你的 keyfile.json 保存在你的代码附近,或者更糟的是,把它上传到公共的地方。基本上就是这样。祝你好运!

                      PS:我也忘了提及这一点,这可能会对遇到与我相同问题的人有所帮助。虽然上述内容在开发中应该可以正常工作,但在某些生产环境中,\n 不会被解释为新行。相反,它将保留在私钥内。将以上所有内容放入 try 语句中,如果您遇到错误:'no key could be detected' 那么这很可能是问题所在。在这种情况下,您需要将所有 \\n 替换为 \n 类似于 Sumit Agrawal 所建议的内容,但有点相反。这是因为在某些环境中,会自动添加 \ 以用于新行指示,例如 \n,以便在有意义的情况下保持它们原样。所以你必须基本上撤消这个。

                      您可以简单地对上述行之一执行以下操作: "private_key": os.environ.get('YOUR_ENV_VAR').replace('\\n', '\n'),

                      但再次尝试将它们打印到日志文件/控制台以查看它们的实际外观。如果您知道字符串中有任何\n,您需要按照说明清理或转换它们。祝你好运!

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2021-02-10
                        • 2019-11-29
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2018-01-12
                        • 1970-01-01
                        相关资源
                        最近更新 更多