La consulta incompleta de Google BigQuery responde en bashs impares

Al consultar BigQuery a través de la API de Python usando:

service.jobs().getQueryResults 

Estamos descubriendo que el primer bash funciona bien: todos los resultados esperados se incluyen en la respuesta. Sin embargo, si la consulta se ejecuta una segunda vez poco después de la primera (aproximadamente en 5 minutos), solo se devuelve un pequeño subconjunto de los resultados (en potencias de 2) casi al instante, sin errores.

Consulte nuestro código completo en: https://github.com/sean-schaefer/pandas/blob/master/pandas/io/gbq.py

¿Alguna idea sobre qué podría causar esto?

Parece que el problema es que devolvemos diferentes números predeterminados de filas para query () y getQueryResults (). Entonces, dependiendo de si su consulta terminó rápidamente (y así no tuvo que usar getQueryResults ()), obtendría más o menos filas.

He archivado un error y deberíamos tener una solución pronto.

La solución (y una buena idea en general) es establecer maxResults tanto para la consulta como para las llamadas a getQueryResults. Y si va a querer muchas filas, es posible que desee ver los resultados usando el token de página devuelto.

A continuación se muestra un ejemplo que lee una página de datos de un trabajo de consulta completado. Se incluirá en la próxima versión de bq.py:

 class _JobTableReader(_TableReader): """A TableReader that reads from a completed job.""" def __init__(self, local_apiclient, project_id, job_id): self.job_id = job_id self.project_id = project_id self._apiclient = local_apiclient def ReadSchemaAndRows(self, max_rows=None): """Read at most max_rows rows from a table and the schema. Args: max_rows: maximum number of rows to return. Raises: BigqueryInterfaceError: when bigquery returns something unexpected. Returns: A tuple where the first item is the list of fields and the second item a list of rows. """ page_token = None rows = [] schema = {} max_rows = max_rows if max_rows is not None else sys.maxint while len(rows) < max_rows: (more_rows, page_token, total_rows, current_schema) = self._ReadOnePage( max_rows=max_rows - len(rows), page_token=page_token) if not schema and current_schema: schema = current_schema.get('fields', {}) max_rows = min(max_rows, total_rows) for row in more_rows: rows.append([entry.get('v', '') for entry in row.get('f', [])]) if not page_token and len(rows) != max_rows: raise BigqueryInterfaceError( 'PageToken missing for %r' % (self,)) if not more_rows and len(rows) != max_rows: raise BigqueryInterfaceError( 'Not enough rows returned by server for %r' % (self,)) return (schema, rows) def _ReadOnePage(self, max_rows, page_token=None): data = self._apiclient.jobs().getQueryResults( maxResults=max_rows, pageToken=page_token, # Sets the timeout to 0 because we assume the table is already ready. timeoutMs=0, projectId=self.project_id, jobId=self.job_id).execute() if not data['jobComplete']: raise BigqueryError('Job %s is not done' % (self,)) page_token = data.get('pageToken', None) total_rows = int(data['totalRows']) schema = data.get('schema', None) rows = data.get('rows', []) return (rows, page_token, total_rows, schema)