我创建了一个 Python 程序,它使用
InstalledAppFlow.run_local_server
弹出 Web 浏览器以让用户进行身份验证。快乐路径工作正常(用户进行身份验证,我获得凭据。)
但是,如果用户在未进行身份验证的情况下关闭网页或只是将其保留,则程序将永远挂起,等待来自 run_local_server 的响应。
所以,有两个问题...
我做了很多谷歌搜索,发现 run_local_server 在本地运行一个简单的 WSGI HTTP 服务器,但找不到任何有关如何解决上述两个问题的信息。
这是代码片段。
flow = InstalledAppFlow.from_client_secrets_file(GOOGLE_CREDS_FILE, GOOGLE_API_SCOPES)
google_credentials = flow.run_local_server(port=0)
# Will hang here forever unless the user authenticates...
以下示例是由 Teraskull 使用我的 Google Calendar Simple API 库实现的:
from oauthlib.oauth2.rfc6749.errors import AccessDeniedError, MismatchingStateError
from gcsa.google_calendar import GoogleCalendar
from concurrent.futures import TimeoutError
from pebble import concurrent
@concurrent.process(timeout=60) # Raise TimeoutError, if the function exceeds the given deadline (in seconds).
def create_process():
return GoogleCalendar('primary', credentials_path='credentials.json')
def do_something():
try:
process = create_process() # Return concurrent process.
calendar = process.result() # Wait for process result. Return calendar instance, or exceptions, if any were raised.
# Catch exceptions, received from process result.
except TimeoutError: # If user did not log into Google Calendar on time.
pass
except AccessDeniedError: # If user denied access to Google Calendar.
pass
except MismatchingStateError: # If user attempted to login using an outdated browser window.
pass
这是一个老问题,但对于任何寻找此问题或类似问题答案的人来说:
run_local_server
现在似乎有一个 timeout_seconds 参数,您可以传递该参数来设置用户在创建的 http 服务器上进行身份验证的时间限制。
try:
creds = flow.run_local_server(port=0, timeout_seconds=100)
except Exception as e:
print(e)
我确实建议将其包装在尝试中,除非我认为库中的超时处理得不好。
这是来自
run_local_server
函数打印出的错误:
'NoneType' object has no attribute 'replace'
无论如何,我刚刚创建了一个自定义错误来返回给用户,告诉他们身份验证请求超时。