24

这可能需要一秒钟来解释,所以请多多包涵:

我正在从事一个需要我提取谷歌分析数据的工作项目。我最初是按照这个链接做的,所以在安装了 API 客户端pip install --upgrade google-api-python-client并设置了类似的东西之后client_secrets.json,它希望安装 gflags 以执行该run()语句。(即credentials = run(FLOW, storage)

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

NotImplementedError:必须安装 gflags 库才能使用 tools.run()。请安装 gflags 或最好切换到使用 tools.run_flow()。

我最初使用 gflags(几个月前),但它与我们的框架(金字塔)不兼容,所以我们删除了它,直到我们找出问题所在。而最好从 gflags 切换到的原因run_flow()是因为 gflags 已被弃用,所以我不想像以前那样使用它。我现在要做的是切换到使用run_flow()

这个问题是run_flow()需要一个命令行参数发送给它,这不是一个命令行应用程序。我发现了一些有用的文档,但我一直坚持为该run_flow()函数构建标志。

在显示代码之前,还要解释一件事。

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

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

第二个链接对于查看它的执行方式非常有帮助,所以现在当我尝试做类似的事情时,sys.argv拉入我正在运行的虚拟环境的位置,pserve也拉入我的.ini文件(它存储我的机器的凭据到运行虚拟环境)。但这会引发错误,因为它期待别的东西,这就是我被卡住的地方。

  • 我不知道我需要构建什么标志对象才能发送run_flow()
  • 我不知道我需要传递哪些 argv 参数才能让语句flags = parser.parse_args(argv[1:])检索正确的信息(我不知道正确的信息应该是什么)

代码:

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)

我调用一个主函数传递sys.argv调用initialize_service

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

    try:
        #do a query and stuff here

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

4

3 回答 3

17
from oauth2client import tools

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

花了一点时间,但我爬出了它让我陷入的两个陷阱:

  1. 必须使用工具中提供的 argparser
  2. 我必须为 args 提供一个空列表,以防止它从命令行读取 args,这是一个问题,因为我是从 unittest 内部运行它(因此不同的 cmdline args)。
于 2014-11-20T10:28:15.497 回答
0

这段代码适用于我的 gmail api。

(这个链接也有帮助。命令行工具

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)
# ...
于 2014-11-22T07:56:39.883 回答
-2

可以通过的标志可以在这里找到,它们是:

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

我还没有弄清楚如何准确地解析它们,我尝试为这三个标志中的每一个传递各种不同的值,但对我没有任何作用。我在这里有一个丰富的问题​​,回答时可能对您有用。

于 2014-08-27T14:28:59.800 回答