Как получить учетные данные Google Analytics без gflags - вместо этого использовать run_flow()?

Это может занять секунду, чтобы объяснить, поэтому, пожалуйста, потерпите меня:

Я работаю над проектом для работы, которая требует от меня получения данных Google Analytics. Первоначально я сделал это по этой ссылке, поэтому после установки клиента 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

Я знал, что это не сработает, потому что мое приложение не является приложением командной строки, а скорее полностью интегрированным сервисом, но я решил, что оно того стоит. Любые мысли о том, как правильно построить объект флаги?

3 ответа

Решение
from oauth2client import tools

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

Немного повозился, но вылез мой путь из двух ловушек, в которые он меня бросил:

  1. должен использовать argparser, предоставленный в инструментах
  2. Мне пришлось выдавать аргументы пустым списком, чтобы они не читали аргументы из командной строки, что было проблемой, потому что я запускаю их из unittest (такие разные аргументы cmdline).

Этот кусок кода работает для меня для API Gmail.

(Также эта ссылка помогла. Инструменты командной строки)

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

Флаги, которые могут быть переданы, могут быть найдены здесь и являются:

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

Мне еще предстоит выяснить, как именно их анализировать, я пытался пройти через различные значения для каждого из этих трех флагов, но у меня ничего не работает. У меня есть задорный вопрос, который может быть полезен для вас, когда на него ответят.