【问题标题】:(BigQuery PY Client Library v0.28) - Fetch result from table 'query' job(BigQuery PY 客户端库 v0.28)- 从表“查询”作业中获取结果
【发布时间】:2018-02-15 04:20:56
【问题描述】:

我正在使用 Python 客户端库 v0.28 学习 BigQuery API https://googlecloudplatform.github.io/google-cloud-python/latest/bigquery/usage.html#run-a-simple-query

编写了这个简单的代码来从表中获取数据

1) 创建客户端对象

client_ = bigquery.Client.from_service_account_json('/Users/xyz/key.json')

2) 开始新的异步查询作业

QUERY =  'SELECT visitid FROM `1234567.ga_sessions_20180101`'
query_job = client_.query(QUERY
                      , job_id=str(uuid.uuid4()))

3) 轮询直到查询完成

while (query_job.state == 'RUNNING'):
    time.sleep(5)
    query_job.reload()

4) 在迭代中获取结果

query_job.reload()        
iter = query_job.result() 

在这个阶段,我想获取表中有多少行。根据文档 GitHub 代码,iter 的类型为 bigquery.table.RowIterator,属性为 [tier.total_rows][1]

5) 但是,在我打印的这个阶段:

print(iter.total_rows)

它不断返回None

我很确定这个表不是空的,干查询格式正确!

对我在这里缺少的任何指针的任何帮助都会非常有帮助......非常感谢!

干杯!

【问题讨论】:

    标签: python google-bigquery


    【解决方案1】:

    您还需要检查 query_job.error_result 以确保查询成功。

    您还可以在 UI 中查看您的作业,这对于调试很有用,使用项目 ID 和作业 ID:

    https://bigquery.cloud.google.com/results/projectid:jobid

    另外,query_job.result() 已经在等待作业完成,因此您无需轮询。

    【讨论】:

    • 感谢您的 cmets! error_result() 为空(返回 None)。有趣的是,一旦我迭代 iter ,然后是 iter.total_rows 和 iter.num_results打印正确的结果(表中的总行数).. 但在迭代之前都产生 0 个结果。
    • 这很有趣。 RowIterator 运行 GET 请求以读取表行。我的猜测是,除非您请求行,否则它可能不会这样做,以避免发送不必要的请求并可能读取多达 10MB 的数据。
    【解决方案2】:

    RowIterator 如何返回None 的当前行为确实令人困惑。幸运的是,this issue, tswast's comment from 10 days ago 表示开发人员正在研究更好的解决方案。

    .total_rows 当前的尴尬行为

    目前,.total_rows 仅在迭代开始时才被初始化。 (在下文中,为清楚起见,我将您的 iter 变量重命名为 row_iter。)

    row_iter = query_job.result()
    itr = iter(row_iter)
    first_row = next(itr)
    print(row_iter.total_rows)  # Now you get a number instead of None.
    

    这很难看,因为要继续迭代,我们必须以不同的方式处理第一行或再次调用row_iter = query_job.result()。

    临时解决方法

    当前可行的替代方法是使用query_job._query_results.total_rows 的值。不幸的是,这是作弊,因为_query_results 是私有的,所以没有理由期望这会在未来起作用。

    未来的行为

    如果实现了tswast的提议,那么row_iter.total_rows会一开始就被初始化,正如你所期望的那样。

    建议

    在我的代码中,我将使用类似的东西

    try:
        num_rows = row_iter.total_rows or query_job._query_results.total_rows
    except NameError:
        num_rows = None
    

    与未来的行为兼容,同时在必要时回退到临时解决方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-06
      • 1970-01-01
      • 2021-06-18
      • 1970-01-01
      • 2019-08-28
      • 1970-01-01
      • 2014-04-09
      • 2015-05-10
      相关资源
      最近更新 更多