为BigQuery Python CLI设置GOOGLE_APPLICATION_CREDENTIALS

77

我正在尝试通过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 = './google-creds.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。然而,错误仍然存在。有人知道问题是什么吗?

提前感谢。


1
所有这些解决方案都依赖于凭据 JSON 文件在服务器上可用,这是不理想的。我真的希望 Google/GCP 能够采用环境变量。 - pdoherty926
1
请不要再添加任何简单陈述“设置GOOGLE_APPLICATION_CREDENTIALS环境变量”的答案。这已经被重复提及了大约20次,没有必要再次说明。 - Liam
17个回答

119

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

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

当我需要在不同的项目之间切换时,我发现这非常有用,因为它需要不同的凭据。


你好,我应该把这些代码放在哪里才能使用不同的Google账户API呢?谢谢。 - ALEXANDER LOZANO
“import os” 只需要在代码开头使用一次。每次切换账户之前都要更改 “os.environ”。将路径更改为账户的路径。 - Roee Anuar
2
非常感谢。对于新手,如果您正在使用Django,请在django项目的设置文件中添加以下代码:import os os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "path_to_your_.json_credential_file" - Amandeep Singh
请注意,您可以在 PowerShell 中使用此命令来获取自己的凭据文件:gcloud auth application-default login - Roee Anuar

56

我不确定 BigQuery,但我正在使用 Google Data Store 进行保存。如果您在Mac上安装了 gcloud sdk,可以尝试运行此命令。

gcloud auth application-default login

这正是我一直在寻找的。每当我尝试使用默认实例(BigQueryOptions.getDefaultInstance().getService())查询任何内容(bigquery)时,都会收到401错误...只需通过“application-default”进行身份验证,它就开始正常工作了。谢谢。 - George Neto
谢谢!我花了很多时间试图弄清楚如何在使用服务账户时使默认凭据起作用,而这正是我想要的。 - tristansokol
那个登录的具体用例有没有记录在文档中? - David
我不记得我从哪里得到这个了 :( 。但是在这里找到了文档 https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login - arthankamal
这是最好的答案,适用于那些想要编写代码而不将开发PC特定文件放入其代码中的人。例如,如果您正在为云函数编码,则不需要手动输入JSON文件条目。使得编码更接近该环境。 - user3507825
我在我的零散空闲时间里花费了几个月,试图弄清楚这个问题,而这就是答案!谢谢。 - Giovanna Fernandes

37

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

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

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

在终端中输入以下内容,可在本次会话中设置变量。

打开你的 .bashrc 文件(UNIX 用户可输入 nano ~/.bashrc),如果看到用户特定别名这个头部,则在其下添加此行:

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

然后输入 source ~/.bashrc 重新加载它,并通过尝试 echo $GOOGLE_APPLICATION_CREDENTIALS 来确认设置是否生效。如果它返回路径,那就没问题了。


2
添加一件事,GOOGLE_APPLICATION_CREDENTIALS json文件可以通过https://cloud.google.com/docs/authentication/getting-started(在“转到创建服务帐户密钥页面”中突出显示)生成。 - Bruce Yo

15

注意:oauth2client已被弃用,您可以使用google.auth.default()代替GoogleCredentials.get_application_default()。首先通过以下方式安装包:

pip install google-auth

从你的代码中,我看到你知道JSON文件的位置。你可以使用服务帐户google.oauth2.service_account模块直接提供凭据,而不是使用默认凭据(来自环境变量)。

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,则将凭据传递给google.cloud.bigquery.Client构造函数。


7
除了使用已经在许多答案中提到的 GOOGLE_APPLICATION_CREDENTIALS 外,还有一种方法可以将生成的 JSON 凭据设置为默认服务帐号:
gcloud auth activate-service-account --key-file=<path to your generated json file>

这将激活一个默认账户(并根据提供的json文件设置凭证),而无需显式设置GOOGLE_APPLICATION_CREDENTIALS,并且在重新登录或重新启动后仍能保持激活状态,而不需要修改.bashrc文件。


6
这是一个C#解决方案。
System.Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS",@"C:\apikey.json");
string Pathsave = System.Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS");

4
这里有另一种解决方法,我认为这里还没有提到。 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的数据存储在环境中,并执行了上述操作。这样,您就不需要将密钥文件keyfile.json保存在代码附近或更糟糕的是上传到公开位置。就这样。祝你好运!

附注:我忘了提到这一点,这可能有助于遇到与我相同问题的人。虽然上面的方法在开发中应该可以正常工作,在某些生产环境中,\n 将不会被解释为换行符。相反,它将保留在私钥中。将以上所有内容放入try语句中,如果出现错误:'找不到任何密钥',那么这很可能是问题所在。在这种情况下,您需要将所有的\\n替换为\n,类似于Sumit Agrawal建议的方式,但是有点相反。因为在某些环境中,对于换行符标识(例如\n),会自动添加 \以便保持它们的状态,如果这有意义的话。所以您必须基本上撤消此操作。

您只需对上面的一行执行以下操作即可:"private_key": os.environ.get('YOUR_ENV_VAR').replace('\\n', '\n'),

但是请再次尝试将它们打印到日志文件/控制台中,以查看它们的实际外观。如果字符串中有任何 \n,则需要进行清理或转换,如上所述。祝你好运!


4
它正在寻找环境变量。但是我可以通过使用应用程序默认凭据来解决Windows平台上的此问题。
我遵循的步骤:
- 安装Google SDK - 然后执行“ gcloud init”步骤,以指定我的默认凭据和默认项目,您可以根据需要随时更改。可在所选择安装Google SDK的“ bin”目录中找到“ gcloud”可执行文件。 - 成功提供凭据后,您可以在位置“ C:\ Users \“ yourusername ”\ AppData \ Roaming \ gcloud \ legacy_credentials \“ youremail ””签到。您可以在那里以JSON格式找到存储的凭据。 这帮助我解决了错误。

3
错误消息中提供的链接https://developers.google.com/identity/protocols/application-default-credentials说明要设置环境变量,以指向包含JSON服务凭据的文件。您似乎设置了一个Python变量。请尝试将终端的环境变量设置为指向正确的文件。
另一个选择是当您不在GCE容器中运行时明确使用其他凭据,比如oauth2client.client.SignedJwtAssertionCredentials并直接将其指向您的客户端密钥,这样就不必通过环境变量进行间接操作。

2
如果您想使用不同的凭证文件而不设置环境变量,可以使用以下代码:
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']))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接