サービスアカウントのJSON鍵ファイルでPythonからGoogleのAPIを使用する

バッチを書くときにサービスアカウントを使う機会が多いのでメモ。

公式ドキュメントではサービスアカウントを使う例が紹介されていないので、Sheets APIのサンプルコードを少し改変してサービスアカウントで認証するようにしてみる。

Python Quickstart  |  Sheets API  |  Google Developers

from __future__ import print_function

import httplib2
from apiclient import discovery
from oauth2client import tools
from oauth2client.service_account import ServiceAccountCredentials

try:
    import argparse

    flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
    flags = None

# If modifying these scopes, delete your previously saved credentials
# at ~/.credentials/sheets.googleapis.com-python-quickstart.json
SCOPES = 'https://www.googleapis.com/auth/spreadsheets.readonly'
CREDENTIALS_FILE = 'credentials.json' # サービスアカウントの鍵ファイル名
APPLICATION_NAME = 'Google Sheets API Python Quickstart'


def get_credentials():
    """サービスアカウントで認証する"""
    return ServiceAccountCredentials.from_json_keyfile_name(CREDENTIALS_FILE, SCOPES)


def main():
    """Shows basic usage of the Sheets API.

    Creates a Sheets API service object and prints the names and majors of
    students in a sample spreadsheet:
    https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
    """
    credentials = get_credentials()
    http = credentials.authorize(httplib2.Http())
    discoveryUrl = ('https://sheets.googleapis.com/$discovery/rest?'
                    'version=v4')
    service = discovery.build('sheets', 'v4', http=http,
                              discoveryServiceUrl=discoveryUrl)

    spreadsheetId = '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms'
    rangeName = 'Class Data!A2:E'
    result = service.spreadsheets().values().get(
        spreadsheetId=spreadsheetId, range=rangeName).execute()
    values = result.get('values', [])

    if not values:
        print('No data found.')
    else:
        print('Name, Major:')
        for row in values:
            # Print columns A and E, which correspond to indices 0 and 4.
            print('%s, %s' % (row[0], row[4]))


if __name__ == '__main__':
    main()

実行してみると、公式ドキュメントのサンプルコードだとURLが表示されてブラウザで認証する形になるが、サービスアカウントを使った場合は認証をパスしたものとして処理が続行される。

$ python main.py
Name, Major:
Alexandra, English
Andrew, Math
Anna, English
Becky, Art
Benjamin, English
...略...

最近BigQueryを使ったときもこのやりかたを使った。

Google BigQuery

Google BigQuery