[Python] gspreadでGoogle Spreadsheetにアクセスするまでのトラブルシューティング

# やること
PythonプログラムからGoogle Spreadsheetにアクセスするまでに発生した問題と、その対策の覚書。


# 方法
Google Spreadsheetを読み書きするためのPythonライブラリである`gspread`を使う。
https://github.com/burnash/gspread


# gspreadの使い方
あらかじめ、`testbook`という名前のスプレッドシートをGoogle Spreadsheet上に作成した。

アクセスは
http://gspread.readthedocs.org/en/latest/oauth2.html
の通りに。
ほぼサンプルそのままの以下を実行する。

```python
    import gspread
    from oauth2client.service_account import ServiceAccountCredentials

    scope = ['https://spreadsheets.google.com/feeds']
    credentials = ServiceAccountCredentials.from_json_keyfile_name(
        'sample-xxxxxx.json', scope)

    gc = gspread.authorize(credentials)
    wks = gc.open("testbook")
```

読み書きの準備としてGoogle spreadsheet上にあるスプレッドシートを開くだけ。
が、失敗した。
以下、上記を動かすまでに発生した複数の問題それぞれについて、内容とその対策。


# トラブルシューティング
## oauth2client.client.HttpAccessTokenRefreshError
まず出たエラー

```console
Traceback (most recent call last):
(中略)
    gc = gspread.authorize(credentials)
  File "/usr/local/lib/python2.7/dist-packages/gspread/client.py", line 331, in authorize
    client.login()
  File "/usr/local/lib/python2.7/dist-packages/gspread/client.py", line 101, in login
    self.auth.refresh(http)
  File "/usr/local/lib/python2.7/dist-packages/oauth2client/client.py", line 659, in refresh
    self._refresh(http.request)
  File "/usr/local/lib/python2.7/dist-packages/oauth2client/client.py", line 864, in _refresh
    self._do_refresh_request(http_request)
  File "/usr/local/lib/python2.7/dist-packages/oauth2client/client.py", line 933, in _do_refresh_request
    raise HttpAccessTokenRefreshError(error_msg, status=resp.status)
oauth2client.client.HttpAccessTokenRefreshError: invalid_grant: Invalid JWT: Token must be a short-lived token and in a reasonable timeframe
```

原因は時刻同期がされたいなかったこと(実時間より遅れていた)。
時刻を同期後に再度実行すると
`oauth2client.client.HttpAccessTokenRefreshError`は出なくなった。

google api - Token must be a short-lived token and in a reasonable timeframe - Stack Overflow
http://stackoverflow.com/questions/36189612/token-must-be-a-short-lived-token-and-in-a-reasonable-timeframe


が、別のエラーで失敗。

## requests.exceptions.SSLError
```console
Traceback (most recent call last):
(中略)
    wks = gc.open("testbook")
  File "/usr/local/lib/python2.7/dist-packages/gspread/client.py", line 145, in open
    feed = self.get_spreadsheets_feed()
  File "/usr/local/lib/python2.7/dist-packages/gspread/client.py", line 231, in get_spreadsheets_feed
    r = self.session.get(url)
  File "/usr/local/lib/python2.7/dist-packages/gspread/httpsession.py", line 75, in get
    return self.request('GET', url, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/gspread/httpsession.py", line 67, in request
    response = func(url, data=data, headers=request_headers)
  File "/usr/lib/python2.7/dist-packages/requests/api.py", line 60, in get
    return request('get', url, **kwargs)
  File "/usr/lib/python2.7/dist-packages/requests/api.py", line 49, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/lib/python2.7/dist-packages/requests/sessions.py", line 457, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/lib/python2.7/dist-packages/requests/sessions.py", line 569, in send
    r = adapter.send(request, **kwargs)
  File "/usr/lib/python2.7/dist-packages/requests/adapters.py", line 420, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError
```

python 2.7系だと発生する？Python 3.5.1では発生しなかった。
python 2.7での当面の対策は旧バージョンの`certifi`を入れること。

```
pip uninstall -y certifi && pip install certifi==2015.04.28
```

ssl - SSL3_GET_SERVER_CERTIFICATE certificate verify failed on Python when requesting (only) *.google.com - Stack Overflow
http://stackoverflow.com/questions/34646942/ssl3-get-server-certificate-certificate-verify-failed-on-python-when-requesting

元々入っていた`certifi`のバージョンは

```console
pip list | grep certifi
certifi (2015.11.20.1)
```

再実行すると、`requests.exceptions.SSLError`は出なくなったが、また別のエラーが発生。


## SpreadsheetNotFound
```
Traceback (most recent call last):
(中略)
    wks = gc.open("testbook")
  File "/usr/local/lib/python2.7/dist-packages/gspread/client.py", line 152, in open
    raise SpreadsheetNotFound
gspread.exceptions.SpreadsheetNotFound
```

`gspread`のドキュメントに以下のような一文がある。

Using OAuth2 for Authorization — gspread 0.3.0 documentation
http://gspread.readthedocs.org/en/latest/oauth2.html

>Go to Google Sheets and share your spreadsheet with an email you have in your json_key['client_email']. Otherwise you’ll get a SpreadsheetNotFound exception when trying to open it.

これの通り、Credential情報のJSONファイル中に記載されている`client_email`に
編集者権限を与えた。

再度実行すると成功した。


# その他トラブルシューティング
## `PyOpenSSL`パッケージのインストールに失敗
PyOpenSSL の依存パッケージインストール(`cffi`パッケージ)中に失敗した。
原因はLinux側の依存パッケージ不足。

`cffi`パッケージのドキュメントを見ると以下の様な一文がある

http://cffi.readthedocs.org/en/latest/installation.html

>on CPython, on non-Windows platforms, you also need to install libffi-dev in order to compile CFFI itself.

```
$ sudo aptitude search libffi-dev
p   libffi-dev                                                                               - Foreign Function Interface library (development files)
$ sudo aptitude install libffi-dev
```

```
pip install PyOpenSSL --upgrade
```

成功