如何断开 Gmail API 服务实例?
How to disconnect Gmail API Service Instance?
在我使用 Gmail API 的 Python3 程序中,我想每隔几个小时重新实例化 Gmail "service" 实例以增强可靠性。我不确定这是否需要提高可靠性,但我认为它会很有用。
因此,当我启动我的程序时,我 运行 下面的函数,如您所见,构建了 Gmail "service" 实例。然后,几个小时后,我再次 运行 相同的代码。但是,这会导致 socker.timeout 错误。我知道这是因为 socket.timeout 错误在我的日志文件中每 6 小时发生一次,这是我重新初始化的频率。
为什么会出现这种情况?在重新连接之前,我是否需要以某种方式断开现有服务?我在 Gmail API 文档或其他论坛帖子中没有找到任何内容。
我的另一个问题是我什至需要重新实例化服务吗?服务实例会永远有效吗? (我的程序旨在连续 运行 永远不碰它)
def gmailAPIInitialize(self):
try:
self.waitForInternet()
logging.info("Initializing the Gmail API Service")
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
else:
logging.error("Unable to find token.pickle file to initialize Gmail Service. Please provide 'token.pickle' file in current directory")
sys.exit(-1)
#flow = InstalledAppFlow.from_client_secrets_file(
#'credentials.json', SCOPES)
#creds = flow.run_local_server(port=0)
# Save the credentials for the next run
service = build('gmail', 'v1', credentials=creds, cache_discovery=False)
self.gmailAPIService = service
logging.info("Successfully initialized the Gmail API Service")
return True
except:
logging.error("An error was encountered while attempting to initialize the Gmail API")
tb = traceback.format_exc()
logging.exception(tb)
return False
重新初始化代码:
currentTime = datetime.datetime.now()
if currentTime > nextRefresh:
logging.info("Refreshing Gmail Connection")
nextRefresh = currentTime + timeDeltaResult
reinitalized = self.gmailAPIInitialize()
if reinitalized is True:
logging.error("Successfully Refreshed Gmail connection")
else:
logging.error("Failed to Refresh Gmail connection")
logging.info("Next Refresh time is at (" + nextRefresh.strftime("%d %b %Y %H:%M:%S") +")")
#RUN MY CALLS AS USUAL TO GMAIL SERVICE
答案:
socket.timeout
当等待响应的单个数据包超过超时 window 时会发生错误。
- 为了保持连接打开,您需要使用服务帐户。
更多信息:
当在实际接收到数据包之前超过接收到预期的新数据包之前的时间时,会发生套接字超时错误。由于这只发生在 open/continuous 连接中,如果您没有足够频繁地向 Gmail API 发出请求,那么这很可能是错误的根源。我不确定这是多久一次,但鉴于您每 6 小时刷新一次,我预计这比令牌的生命周期更长。
您建立的与服务器的连接将为您提供一个授权令牌,该令牌在需要更新之前具有有限的生命周期。但是,您收到的刷新令牌在某些情况下可能会过期,例如,如果您有多个应用程序实例 运行ning 并行。
根据文档:
Access tokens periodically expire and become invalid credentials for a related API request. You can refresh an access token without prompting the user for permission (including when the user is not present) if you requested offline access to the scopes associated with the token.
和:
Requesting offline access is a requirement for any application that needs to access a Google API when the user is not present. For example, an app that performs backup services or executes actions at predetermined times needs to be able to refresh its access token when the user is not present
因此,为了保持您的刷新令牌有效,您需要在调用授权流程时将 access_type
关键字参数设置为 offline
。
在python中:
authorization_url, state = flow.authorization_url(
# Enable offline access so that you can refresh an access token without
# re-prompting the user for permission. Recommended for web server apps.
access_type='offline',
# Enable incremental authorization. Recommended as a best practice.
include_granted_scopes='true')
有关在不重新提示用户权限的情况下刷新访问令牌的更多信息can be read about here
服务帐户:
Service Accounts,但是不需要重新获取令牌来维持访问。您可以为服务帐户提供 运行 您的应用程序所需的范围,或者它可以通过这种方式模拟用户和 运行 所需的应用程序服务。 Google 有非常详尽的服务帐户文档,我认为可以在下面找到对您有帮助的链接。
参考文献:
- Understanding service accounts | Cloud IAM Documentation
- Service accounts | Cloud IAM Documentation
- Using OAuth2 for Web Server Applications
相关问题:
- ConnectionTimeout vs SocketTimeout
在我使用 Gmail API 的 Python3 程序中,我想每隔几个小时重新实例化 Gmail "service" 实例以增强可靠性。我不确定这是否需要提高可靠性,但我认为它会很有用。 因此,当我启动我的程序时,我 运行 下面的函数,如您所见,构建了 Gmail "service" 实例。然后,几个小时后,我再次 运行 相同的代码。但是,这会导致 socker.timeout 错误。我知道这是因为 socket.timeout 错误在我的日志文件中每 6 小时发生一次,这是我重新初始化的频率。
为什么会出现这种情况?在重新连接之前,我是否需要以某种方式断开现有服务?我在 Gmail API 文档或其他论坛帖子中没有找到任何内容。
我的另一个问题是我什至需要重新实例化服务吗?服务实例会永远有效吗? (我的程序旨在连续 运行 永远不碰它)
def gmailAPIInitialize(self):
try:
self.waitForInternet()
logging.info("Initializing the Gmail API Service")
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
else:
logging.error("Unable to find token.pickle file to initialize Gmail Service. Please provide 'token.pickle' file in current directory")
sys.exit(-1)
#flow = InstalledAppFlow.from_client_secrets_file(
#'credentials.json', SCOPES)
#creds = flow.run_local_server(port=0)
# Save the credentials for the next run
service = build('gmail', 'v1', credentials=creds, cache_discovery=False)
self.gmailAPIService = service
logging.info("Successfully initialized the Gmail API Service")
return True
except:
logging.error("An error was encountered while attempting to initialize the Gmail API")
tb = traceback.format_exc()
logging.exception(tb)
return False
重新初始化代码:
currentTime = datetime.datetime.now()
if currentTime > nextRefresh:
logging.info("Refreshing Gmail Connection")
nextRefresh = currentTime + timeDeltaResult
reinitalized = self.gmailAPIInitialize()
if reinitalized is True:
logging.error("Successfully Refreshed Gmail connection")
else:
logging.error("Failed to Refresh Gmail connection")
logging.info("Next Refresh time is at (" + nextRefresh.strftime("%d %b %Y %H:%M:%S") +")")
#RUN MY CALLS AS USUAL TO GMAIL SERVICE
答案:
socket.timeout
当等待响应的单个数据包超过超时 window 时会发生错误。- 为了保持连接打开,您需要使用服务帐户。
更多信息:
当在实际接收到数据包之前超过接收到预期的新数据包之前的时间时,会发生套接字超时错误。由于这只发生在 open/continuous 连接中,如果您没有足够频繁地向 Gmail API 发出请求,那么这很可能是错误的根源。我不确定这是多久一次,但鉴于您每 6 小时刷新一次,我预计这比令牌的生命周期更长。
您建立的与服务器的连接将为您提供一个授权令牌,该令牌在需要更新之前具有有限的生命周期。但是,您收到的刷新令牌在某些情况下可能会过期,例如,如果您有多个应用程序实例 运行ning 并行。
根据文档:
Access tokens periodically expire and become invalid credentials for a related API request. You can refresh an access token without prompting the user for permission (including when the user is not present) if you requested offline access to the scopes associated with the token.
和:
Requesting offline access is a requirement for any application that needs to access a Google API when the user is not present. For example, an app that performs backup services or executes actions at predetermined times needs to be able to refresh its access token when the user is not present
因此,为了保持您的刷新令牌有效,您需要在调用授权流程时将 access_type
关键字参数设置为 offline
。
在python中:
authorization_url, state = flow.authorization_url(
# Enable offline access so that you can refresh an access token without
# re-prompting the user for permission. Recommended for web server apps.
access_type='offline',
# Enable incremental authorization. Recommended as a best practice.
include_granted_scopes='true')
有关在不重新提示用户权限的情况下刷新访问令牌的更多信息can be read about here
服务帐户:
Service Accounts,但是不需要重新获取令牌来维持访问。您可以为服务帐户提供 运行 您的应用程序所需的范围,或者它可以通过这种方式模拟用户和 运行 所需的应用程序服务。 Google 有非常详尽的服务帐户文档,我认为可以在下面找到对您有帮助的链接。
参考文献:
- Understanding service accounts | Cloud IAM Documentation
- Service accounts | Cloud IAM Documentation
- Using OAuth2 for Web Server Applications
相关问题:
- ConnectionTimeout vs SocketTimeout