Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
106 views
in Technique[技术] by (71.8m points)

python - How to disconnect Gmail API Service Instance?

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.

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

Re-initializing code:

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
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Answers:

  • socket.timeout errors occur when the timeout window is exceeded when waiting on individual packets of a response.
  • In order to keep a connection open, you need to use a service account.

More Information:

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.

According to the documentation:

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.

and:

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

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.

In 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

Service Accounts:

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.

I hope this is helpful to you!

References:

Related Questions:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...