如何断开Gmail API服务实例的连接? [英] How to disconnect Gmail API Service Instance?

查看:64
本文介绍了如何断开Gmail API服务实例的连接?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用Gmail API的Python3程序中,我希望每隔几个小时重新实例化一次Gmail服务"实例,以提高可靠性.我不确定是否需要这样做以提高可靠性,但我认为这样做会很有用.因此,当我启动程序时,我将运行以下功能,如您所见,该功能将构建Gmail服务"实例.然后,几个小时后,我再次运行相同的代码.但是,这会导致socker.timeout错误.我知道这是因为在日志文件中,socket.timeout错误每隔6个小时就会发生一次,这是我重新初始化的频率.

In my Python3 program that uses the Gmail API, I want to re-instantiate the Gmail "service" instance every few hours for the purpose of enhanced reliability. I am not certain if this is required to better reliability, but I thought it would be useful. So, when I start my program, I run the below function, which as you can see, builds the Gmail "service" instance. Then, after a few hours, I run the same code again. However, this results in socker.timeout errors. I know this because the socket.timeout errors occur every 6 hours in my log file, which is how often I re-initialize.

为什么会这样?重新连接之前,我是否需要以某种方式断开现有服务?我没有在Gmail API文档或其他论坛帖子中找到任何内容.

Why does this occur? Do I somehow need to disconnect my existing service, before reconnecting again? I did not find anything in the Gmail API Documentation or in other forum posts.

我的另一个问题是,我是否还需要重新实例化该服务?服务实例将永远有效吗?(我的程序旨在保持连续并且永远运行而不会碰到它)

My other question is that do I even need to re-instantiate the service? Will the service instance be valid forever? (My program is intended to be continuous and run forever without touching it)

    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 错误.
  • 为了保持连接打开状态,您需要使用服务帐户.
  • 当在实际接收到数据包之前超过了接收预期的新数据包之前的时间时,就会发生套接字超时错误.由于这种情况仅发生在开放/连续连接中,因此如果您对Gmail API的请求频率不够高,则很可能是错误的根源.我不确定这是多久一次,但是鉴于您每隔6个小时刷新一次,我希望这比令牌的寿命更长.

    The socket timeout error occurs when the time before the receipt of an expected new packet is exceeded before a packet is actually received. As this occurs only for open/continuous connections, if you aren't making requests frequently enough to the Gmail API then it is likely that this is the origin of the error. I'm not sure how often this is, but given your refresh is every 6 hours I would expect this is longer than the token's lifetime.

    与您建立的服务器的连接将为您提供一个授权令牌,该令牌的寿命有限,需要更新之前.但是,您收到的刷新令牌在某些情况下可能会过期,例如,如果您有多个并行运行的应用程序实例.

    The connection to the server that you establish will provide you an authorisation token, which has a limited lifespan before it needs to be renewed. The refresh token you receive however, could expire under certain circumstances, for example if you have multiple instances of the application running in parallel.

    根据文档:

    访问令牌会定期过期,并成为相关API请求的无效凭据.如果您请求脱机访问与令牌关联的范围,则可以刷新访问令牌而不提示用户许可(包括当用户不存在时).

    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.

    和:

    请求离线访问是任何在用户不存在时需要访问Google API的应用程序的要求.例如,在预定时间执行备份服务或执行操作的应用需要能够在用户不存在时刷新其访问令牌.

    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 .

    So in order to keep your refresh token valid, you need to set the access_type keyword argument to offline when calling the authorisation flow.

    在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')
    

    有关刷新访问令牌而不重新提示用户权限的更多信息可以在这里阅读

    More information about refreshing access tokens without re-prompting users for permissions can be read about here

    服务帐户,但是,无需重新获取令牌以维护访问权限.您可以为服务帐户提供运行应用程序所需的范围,也可以模拟用户并以这种方式运行所需的应用程序服务.Google为服务帐户提供了非常详尽的文档,我认为对您有帮助的链接可以在下面找到.

    Service Accounts, however, do not need to re-obtain tokens to maintain access. You can either give the service account the scopes needed to run your application, or it can impersonate a user and run the required application services this way. Google has pretty thorough documentation for service accounts, the links which I think will be of help to you can be found below.

    希望对您有帮助!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆