如何在Apache Airflow中查询Google Big Query并以Pandas Dataframe的形式返回结果?

时间:2019-06-19 17:17:51

标签: google-bigquery airflow

我正在尝试将bigquery查询保存到自定义Airflow运算符中的数据框。

我尝试使用airflow.contrib.hooks.bigquery_hook和get_pandas_df方法。该任务被困在身份验证上,因为它希望我手动访问URL进行身份验证。

结果,我正在对身份验证进行硬编码。这可行,但绝对不理想。

工作但不理想(凭据是硬编码的):

def execute(self, context):
        os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'my-file-location.json'
        client = bigquery.Client()

        job_config = bigquery.QueryJobConfig()

        df = client.query(
            self.query,
            location="US",
            job_config=job_config,).to_dataframe()

不起作用:

def execute(self, context):
    bq  = BigQueryHook(bigquery_conn_id=self.gcp_conn_id, delegate_to=None,use_legacy_sql=True, location='US')
    df = bq.get_pandas_df(self.query)

此代码无法通过身份验证。这是日志:[2019-06-19 12:56:05,526] {logging_mixin.py:95}信息-请访问此URL以授权此应用程序。

3 个答案:

答案 0 :(得分:0)

似乎没有为该挂钩指定服务帐户或密钥路径。

此处是设置GCP连接的指南。 https://github.com/apache/airflow/blob/1.10.3/docs/howto/connection/gcp.rst

在气流配置文件中设置AIRFLOW_CONN_BIGQUERY_DEFAULT环境变量。

如果凭据在气流过程可访问的路径中可用,则可以使用key_path查询参数。
否则,请将key_dict查询参数设置为凭据文件的URL编码JSON内容。

AIRFLOW_CONN_BIGQUERY_DEFAULT=google-cloud-platform://?extra__google_cloud_platform__key_path=%2Fkeys%2Fkey.json&extra__google_cloud_platform__scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform&extra__google_cloud_platform__project=airflow&extra__google_cloud_platform__num_retries=5

答案 1 :(得分:0)

作为@Oluwafemi的响应的补充,现在您已经拥有BigQueryHook的凭据,您可以使用它们来实例化BigQueryPandasConnector。根据文档,此连接器:

  

......使Airflow可以将BigQuery与Pandas一起使用,而无需强制使用三足式OAuth连接...

这是一个例子:

def execute(self, context):

    bq = BigQueryHook(bigquery_conn_id=self.gcp_conn_id, delegate_to=None,use_legacy_sql=True, location='US')
    pd = BigQueryPandasConnector(bq._get_field('project'), bq.get_service())
    df = pd.read_gbq(self.query)

答案 2 :(得分:0)

以某种方式我无法使BigQueryPandasConnector工作。我最终最终得到的是使用BigQueryHook的凭据通过BigQuery的官方Python客户端创建普通的bigquery.client.Client

这是一个例子:

from google.cloud import bigquery

bq_hook = BigQueryHook(bigquery_conn_id=bigquery_conn_id, use_legacy_sql=False)
bq_client = bigquery.Client(project = bq_hook._get_field("project"), credentials = bq_hook._get_credentials())
df = bq_client.query(sql).to_dataframe()