How to get Google Analytics credentials without gf

2019-01-18 02:46发布

问题:

This may take a second to explain so please bear with me:

I'm working on a project for work that requires me to pull in google analytics data. I originally did this following this link, so after installing the API client pip install --upgrade google-api-python-client and setting things up like the client_secrets.json, it wanted gflags to be installed in order to execute the run() statement. (i.e credentials = run(FLOW, storage))

Now, I was getting the error message to install gflags or better to use run_flow() (exact error message was this):

NotImplementedError: The gflags library must be installed to use tools.run(). Please install gflags or preferably switch to using tools.run_flow().

I originally used gflags (a few months ago), but it wasn't compatible with our framework (pyramid), so we removed it until we could figure out what the issue was. And the reason why it's preferable to switch from gflags to run_flow() is because gflags has been deprecated, so I don't want to use it like I had. What I'm trying to do now is switch over to using run_flow()

The issue with this is run_flow() expects a command line argument to be sent to it and this is not a command line application. I found some documentation that was helpful but I'm stuck on building the flags for the run_flow() function.

Before showing code one more thing to explain.

run_flow() takes three arguments (documentation here). It takes the flow and storage just like run() does, but it also takes a flags object. the gflags library built a flags ArgumentParser object that was used in the oauth2client execution method.

a few other links that were helpful in building the argumentParser object:

  • Link 1: https://google-api-python-client.googlecode.com/hg/docs/epy/oauth2client.tools-module.html
  • Link 2: https://developers.google.com/compute/docs/api/python-guide

The second link is very helpful to see how it would be executed, so now when I try to do something similar, sys.argv pulls in the location of my virtual environment that is running aka pserve and also pulls in my .ini file (which stores credentials for my machine to run the virtual environment). But that throws an error because its expecting something else, and this is where I'm stuck.

  • I don't know what flags object I need to build to send through run_flow()
  • I don't know what argv arguments I need passed in order for the statement flags = parser.parse_args(argv[1:]) to retrieve the correct information (I don't know what the correct information is supposed to be)

Code:

CLIENT_SECRETS = client_file.uri
MISSING_CLIENT_SECRETS_MESSAGE = '%s is missing' % CLIENT_SECRETS
FLOW = flow_from_clientsecrets(
    CLIENT_SECRETS,
    scope='https://www.googleapis.com/auth/analytics.readonly',
    message=MISSING_CLIENT_SECRETS_MESSAGE
)
TOKEN_FILE_NAME = 'analytics.dat'

def prepare_credentials(self, argv):
    storage = Storage(self.TOKEN_FILE_NAME)
    credentials = storage.get()

    if credentials is None or credentials.invalid:
        parser = argparse.ArgumentParser(description=__doc__,
            formatter_class=argparse.RawDescriptionHelpFormatter,
            parents=[tools.argparser])
        flags = parser.parse_args(argv[1:]) # i could also do just argv, both error
        credentials = run_flow(self.FLOW, storage, flags) 
    return credentials

def initialize_service(self, argv):
    http = httplib2.Http()
    credentials = self.prepare_credentials(self, argv)
    http = credentials.authorize(http)
    return build('analytics', 'v3', http=http)

I call a main function passing sys.argv that calls the initialize_service

def main(self, argv):
    service = self.initialize_service(self, argv)

    try:
        #do a query and stuff here

I knew this wouldn't work because my application is not a command line application but rather a full integrated service but I figured it was worth a shot. Any thoughts on how to build the flags object correctly?

回答1:

from oauth2client import tools

flags = tools.argparser.parse_args(args=[])
credentials = tools.run_flow(flow, storage, flags)

Took a bit of mucking about but climbed my way out the two traps it dropped me into:

  1. have to use the argparser provided in tools
  2. I had to feed args an empty list to prevent it from reading args off the command line, which was a problem because I'm running it from inside a unittest (so different cmdline args).


回答2:

This piece of code works for me for the gmail api.

(Also this link helped. Command-line tools)

import argparse
import httplib2
from oauth2client.tools import run_flow
from oauth2client.tools import argparser
from oauth2client.file import Storage

CLIENT_SECRETS_FILE = "your_file.json"
OAUTH_SCOPE = 'https://www.googleapis.com/auth/gmail.readonly'

STORAGE = Storage("storage")

flow = flow_from_clientsecrets(CLIENT_SECRETS_FILE, scope=OAUTH_SCOPE)
http = httplib2.Http()

credentials = STORAGE.get()

if credentials is None or credentials.invalid:
    #magic 
    parser = argparse.ArgumentParser(parents=[argparser])
    flags = parser.parse_args()
    credentials = run_flow(flow, STORAGE, flags, http=http)


http = credentials.authorize(http)
gmApi = build('gmail', 'v1', http=http)
# ...


回答3:

The flags that can be passed can be found here and are:

  --auth_host_name: Host name to use when running a local web server
    to handle redirects during OAuth authorization.
    (default: 'localhost')

  --auth_host_port: Port to use when running a local web server to handle
    redirects during OAuth authorization.;
    repeat this option to specify a list of values
    (default: '[8080, 8090]')
    (an integer)

  --[no]auth_local_webserver: Run a local web server to handle redirects
    during OAuth authorization.
    (default: 'true')

I have yet to work out how exactly to parse them, I have tried passing through various different values for each of these three flags but nothing works for me. I have a bountied question here that may be of use for you when answered.