Я использую скрипт быстрого запуска Google Python отсюда: https://developers.google.com/calendar/quickstart/python
Он отлично работает в нормальных условиях. Я могу разрешить ему доступ к моей учетной записи Gmail, и он может создавать записи Календаря Google.
Если я войду в свою учетную запись Gmail через браузер, перейдите в раздел Безопасность и отзовите доступ моего приложения к моей учетной записи Google,скрипт быстрого старта не подхватывает его. Он просто падает:
$ python quickstart.py
Getting the upcoming 10 events
Traceback (most recent call last):
File "quickstart.py", line 52, in <module>
main()
File "quickstart.py", line 42, in main
orderBy='startTime').execute()
File "/opt/my_project/venv3/lib/python3.6/site-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "/opt/my_project/venv3/lib/python3.6/site-packages/googleapiclient/http.py", line 851, in execute
method=str(self.method), body=self.body, headers=self.headers)
File "/opt/my_project/venv3/lib/python3.6/site-packages/googleapiclient/http.py", line 165, in _retry_request
resp, content = http.request(uri, method, *args, **kwargs)
File "/opt/my_project/venv3/lib/python3.6/site-packages/google_auth_httplib2.py", line 213, in request
self.credentials.refresh(self._request)
File "/opt/my_project/venv3/lib/python3.6/site-packages/google/oauth2/credentials.py", line 136, in refresh
self._client_secret))
File "/opt/my_project/venv3/lib/python3.6/site-packages/google/oauth2/_client.py", line 237, in refresh_grant
response_data = _token_endpoint_request(request, token_uri, body)
File "/opt/my_project/venv3/lib/python3.6/site-packages/google/oauth2/_client.py", line 111, in _token_endpoint_request
_handle_error_response(response_body)
File "/opt/my_project/venv3/lib/python3.6/site-packages/google/oauth2/_client.py", line 61, in _handle_error_response
error_details, response_body)
google.auth.exceptions.RefreshError: ('invalid_grant: Token has been expired or revoked.', '{\n "error": "invalid_grant",\n "error_description": "Token has been expired or revoked."\n}')
Если я добавлю несколько строк отладки непосредственно перед строкой, которая выдает исключение, я вижу это:
creds.valid: True
creds.expired: False
Я знаю, что могу просто поймать google.auth.exceptions.RefreshError. Проблема, с которой я столкнулся, состоит в том, что в начале файла quickstart.py имеется целый раздел кода, целью которого является определение допустимости токена, но, по-видимому, он не может обнаружить этот довольно простой сценарий, и исключение не выдается доЯ на самом деле пытаюсь использовать токен для выполнения команды. Помещение каждого отдельного выполнения (или, по крайней мере, первого) в блок try-exc на случай, если первая часть скрипта не может выполнить свою задачу по обнаружению того, что токен отозван, кажется глупым.
Есть лиспособ обнаружить, что сертификат был отозван, прежде чем я на самом деле пытаюсь его использовать? Почему не работают creds.valid и creds.expired?
Обновление. Похоже, что если вы подождете достаточно долго (несколько минут или часов - не уверены), в конечном итоге отобразятся creds.valid и creds.expired. что учетные данные больше не действительны. Однако в этот промежуток времени, когда учетные данные кажутся действительными, но не могут быть использованы, достаточно, чтобы моя программа аварийно завершилась, если я не обработал ее правильно.
Обновление 2: единственное, что яМожно подумать просто запустить что-то вроде:
from googleapiclient.discovery import build
from google.auth.exceptions import RefreshError
...
try:
service = build('calendar', 'v3', credentials=creds)
service.events().list(calendarId='primary', maxResults=1).execute()
except RefreshError:
...
...
сразу после кода, который проверяет, действительны ли учетные данные. Вроде как окончательная проверка. Это работает, но выглядит немного грязно, поскольку требует дополнительного вызова к серверам API Google, и в основном это именно то, что я сказал выше - поместить первое выполнение в блок try-Кроме. Нет лучшего способа?