如何在没有gflags的情况下获取Google Analytics凭据 - 使用run_flow()代替?

时间:2021-04-28 15:15:41

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

我正在开展一项工作项目,要求我提供谷歌分析数据。我最初在这个链接之后做了这个,所以在安装API客户端pip install --upgrade google-api-python-client并设置像client_secrets.json这样的东西后,它想要安装gflags以便执行run()声明。 (即凭证=运行(流程,存储))

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

现在,我收到错误消息以安装gflags或更好地使用run_flow()(确切的错误消息是这样的):

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

NotImplementedError:必须安装gflags库才能使用tools.run()。请安装gflags或最好切换到使用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()

我最初使用gflags(几个月前),但它与我们的框架(金字塔)不兼容,所以我们删除它直到我们弄清楚问题是什么。而且最好从gflags切换到run_flow()的原因是因为gflags已被弃用,所以我不想像我那样使用它。我现在要做的是切换到使用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.

这个问题是run_flow()期望将命令行参数发送给它,这不是命令行应用程序。我找到了一些有用的文档,但我仍然坚持为run_flow()函数构建标志。

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.

run_flow()有三个参数(文档在这里)。它像run()一样接受流和存储,但它也需要一个flags对象。 gflags库构建了一个标志ArgumentParser对象,该对象在oauth2client执行方法中使用。

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

一些有助于构建argumentParser对象的其他链接:

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.

第二个链接非常有助于查看它将如何执行,所以现在当我尝试执行类似的操作时,sys.argv会拉入我运行的名为pserve的虚拟环境的位置,并且还会拉入我的.ini文件(存储我的机器运行虚拟环境的凭据)。但这引发了一个错误,因为它期待别的东西,这就是我被困住的地方。

  • I don't know what flags object I need to build to send through run_flow()
  • 我不知道我需要构建什么标志对象来通过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)
  • 我不知道我需要传递什么argv参数才能使语句flags = parser.parse_args(argv [1:])检索正确的信息(我不知道应该是什么样的正确信息)

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

我调用一个传递sys.argv的main函数来调用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?

我知道这不起作用,因为我的应用程序不是一个命令行应用程序,而是一个完整的集成服务,但我认为它值得一试。有关如何正确构建标志对象的任何想法?

3 个解决方案

#1


14  

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. 必须使用工具中提供的argparser

  3. 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).
  4. 我必须向args提供一个空列表以防止它从命令行读取args,这是一个问题,因为我是从unittest内部运行它(所以不同的cmdline args)。

#2


0  

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

这段代码适用于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


-2  

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.

我还没有弄清楚如何解析它们,我已经尝试为这三个标志中的每一个传递各种不同的值,但对我来说没有任何作用。我在这里有一个有价值的问题,在回答时可能会对你有用。

#1


14  

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. 必须使用工具中提供的argparser

  3. 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).
  4. 我必须向args提供一个空列表以防止它从命令行读取args,这是一个问题,因为我是从unittest内部运行它(所以不同的cmdline args)。

#2


0  

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

这段代码适用于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


-2  

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.

我还没有弄清楚如何解析它们,我已经尝试为这三个标志中的每一个传递各种不同的值,但对我来说没有任何作用。我在这里有一个有价值的问题,在回答时可能会对你有用。