我正在使用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
我很确定这个表不是空的,干查询格式正确!
对任何指针的任何帮助我在这里缺少的东西真的很有用......非常感谢!
干杯!
答案 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
与将来的行为兼容,同时在必要时转而使用临时解决方法。