Архив метки: fusion tables

Google API Python Client: сохранение access token при использовании service account

Проблема: текущий python клиент Google API не хранит access token в режиме доступа к API с помощью service account, что происходит из-за отсутствия полноценной поддержки хранилища данных (oauth2client.file.Storage). При каждом новом запросе к функциям API необходим дополнительный запрос на обновление access token, что занимает немало времени (около секунды).

Решение: изменение исходного кода oauth2client.client.

Теперь следующий код запроса к функциям API будет работать:

import httplib2
from apiclient.discovery import build
from oauth2client.client import SignedJwtAssertionCredentials
from oauth2client.file import Storage

logging.getLogger().setLevel(logging.INFO)

f = file('616591315bc79b4b964cf6c2d4afbe3b1a82a1c1-privatekey.p12', 'rb')
key = f.read()
f.close()

# First argument is e-mail provided in Google API Console for service account
credentials = SignedJwtAssertionCredentials(
    '...@developer.gserviceaccount.com',
    key,
    scope='https://www.googleapis.com/auth/fusiontables')
storage = Storage('fusion.dat')
credentials.set_store(storage)

http = httplib2.Http()
http = credentials.authorize(http)

service = build("fusiontables", "v1", http=http)
response = service.query().sqlGet(sql='SELECT Location FROM 1gvB3SedL89vG5r1128nUN5ICyyw7Wio5g1w1mbk LIMIT 10').execute(http)
for row in response['rows']:
    print unicode(row[0]).encode('utf-8')

При текущей версии клиента код выдавал ошибку:

UnicodeDecodeError: 'utf8' codec can't decode byte 0x82 in position 1: invalid start byte

Я немного поковырялся в исходниках и исправил ситуацию. Исходный файл пропатченного client.py для пакета oauth2client прикрепляю к этой записи. Коммит пока не делал, т.к. не до конца уверен, что изменения не затронут другие режимы (client, web-application).

PS: кстати, если у вас при использовании клиента даже в простом режиме появляется ошибка «invalid_grant» – проверьте системное время! Я долго бился об стенку, пока на нашел такое предположение, и оно оказалось верным! Может быть, это из-за second leap?! Не скажу точно.

Скачать пропатченный исходный код oauth2client.client.

Google API Python Client: Google Fusion Tables

Наконец-то я получил доступ к google fusion tables API с помощью google-api-python-client. У этой библиотеки действительно странноватый интерфейс, но всё стало гораздо понятней после недавнего полноценного переезда Fusion API на новую версию.

Рабочий код:

import httplib2
from apiclient.discovery import build
from oauth2client.client import SignedJwtAssertionCredentials

# Here's the file you get from API Console -> Service Account.
f = file('key.p12', 'rb')
key = f.read()
f.close()

# Create an httplib2.Http object to handle our HTTP requests and authorize it
  # with the Credentials. Note that the first parameter, service_account_name,
  # is the Email address created for the Service account. It must be the email
  # address associated with the key that was created.
credentials = SignedJwtAssertionCredentials(
    '...@developer.gserviceaccount.com',
    key,
    scope='https://www.googleapis.com/auth/fusiontables')
http = httplib2.Http()
http = credentials.authorize(http)

service = build("fusiontables", "v1", http=http)
# For example, let make SQL query to SELECT ALL from Table with
# id = 1gvB3SedL89vG5r1128nUN5ICyyw7Wio5g1w1mbk
print(service.query().sql(sql='SELECT * FROM 1gvB3SedL89vG5r1128nUN5ICyyw7Wio5g1w1mbk').execute())

Можно использовать функцию help, чтобы получить документацию по методам:

service = build("fusiontables", "v1")
help(service)
help(service.query())

Для последней команды вы получите что-то типа такого:


class Resource(__builtin__.object)
 |  A class for interacting with a resource.
 |
 |  Methods defined here:
 |
 |  __init__(self)
 |
 |  sql = method(self, **kwargs)
 |      Executes an SQL SELECT/INSERT/UPDATE/DELETE/SHOW/DESCRIBE statement.
 |
 |      Args:
 |        pp: string, A parameter
 |        hdrs: boolean, Should column names be included (in the first row)?. Default is true.
 |        typed: boolean, Should typed values be returned in the (JSON) response -- numbers for numeric values and parsed geometries for KML values? Default is true.
 |        strict: string, A parameter
 |        userip: string, A parameter
 |        sql: string, An SQL SELECT/SHOW/DESCRIBE/INSERT/UPDATE/DELETE statement. (required)
 |        trace: string, A parameter
 |
 |      Returns:
 |        An object of the form:
 |
 |          { # Represents a response to an sql statement.
 |          "kind": "fusiontables#sqlresponse", # Type name: a template for an individual table.
 |          "rows": [ # The rows in the table. For each cell we print out whatever cell value (e.g., numeric, string) exists. Thus it is important that each cell contains only one value.
 |            [
 |              [
 |                "",
 |              ],
 |            ],
 |          ],
 |          "columns": [ # Columns in the table.
 |            "A String",
 |          ],
 |        }
 |
 |  sqlGet = method(self, **kwargs)
 |      Executes an SQL SELECT/SHOW/DESCRIBE statement.
 |
 |      Args:
 |        pp: string, A parameter
 |        hdrs: boolean, Should column names be included (in the first row)?. Default is true.
 |        typed: boolean, Should typed values be returned in the (JSON) response -- numbers for numeric values and parsed geometries for KML values? Default is true.
 |        strict: string, A parameter
 |        userip: string, A parameter
 |        sql: string, An SQL SELECT/SHOW/DESCRIBE statement. (required)
 |        trace: string, A parameter
 |
 |      Returns:
 |        An object of the form:
 |
 |          { # Represents a response to an sql statement.
 |          "kind": "fusiontables#sqlresponse", # Type name: a template for an individual table.
 |          "rows": [ # The rows in the table. For each cell we print out whatever cell value (e.g., numeric, string) exists. Thus it is important that each cell contains only one value.
 |            [
 |              [
 |                "",
 |              ],
 |            ],
 |          ],
 |          "columns": [ # Columns in the table.
 |            "A String",
 |          ],
 |        }
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |
 |  __dict__
 |      dictionary for instance variables (if defined)
 |
 |  __weakref__
 |      list of weak references to the object (if defined)

Up.: нашел список методов доступа к Fusion Tables. В нём вся та же информация, что даёт функция help(), но в виде веб-страниц. Кстати, там есть инфа и по другим API.