(BigQuery PY Client Library v0.28) - 从表'query'作业中获取结果

时间:2018-02-15 04:20:56

标签: python google-bigquery

我正在使用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

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

对任何指针的任何帮助我在这里缺少的东西真的很有用......非常感谢!

干杯!

2 个答案:

答案 0 :(得分:2)

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

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

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

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

答案 1 :(得分:0)

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

与将来的行为兼容,同时在必要时转而使用临时解决方法。