【问题标题】:Python global variable changing for some functions but not others in loopPython 全局变量在某些函数中更改,但在循环中其他函数没有更改
【发布时间】:2020-11-23 22:09:30
【问题描述】:

我确信以前有人回答过类似的问题,但这些帖子似乎已经在有关全局变量和循环的更受欢迎的问题中消失了。

我正在尝试编写一个循环来逐步执行 Google Analytics API,每天提取数据。我确信已经有一些包可以做到这一点,但这对我来说是一种学习体验。

我卡住的地方是我的循环似乎在进行正确的天数,但是发送到 GA Reporting API (V4) 的实际请求并未使用全局变量进行更新,即使是简单的打印() 似乎表明它确实更新了。

这是我的代码:

# Reporting API V4

from apiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials

# Import JSON
import json

# Open JSON config file
jsonConfig = open("config.json", "r")

# Parse the JSON file
configRead = json.loads(jsonConfig.read())

# Define global vars

SCOPES = ['https://www.googleapis.com/auth/analytics.readonly']
KEY_FILE_LOCATION = configRead['keyFileLocation']
VIEW_ID = 12345678 # made up for this exercise

startDate = 732
endDate = 732

# Define report #1
request1 = {
        'reportRequests': 
        [
          {
            'viewId': VIEW_ID,
            'dateRanges': 
            [
              {
                'startDate': f'{startDate}daysAgo',
                'endDate': f'{endDate}daysAgo'
              }
            ],
            'metrics': 
            [
              {
                'expression': 'ga:sessions'
              }
            ],
            'dimensions': 
            [
              {
                'name': 'ga:date'
              }
            ],
            'pageSize': 1
          }
        ]
      }

def initialize_analyticsreporting():
  # Initializes an Analytics Reporting API V4 service object.
  # Returns: An authorized Analytics Reporting API V4 service object.

  credentials = ServiceAccountCredentials.from_json_keyfile_name(
      KEY_FILE_LOCATION, SCOPES)

  # Build the service object
  analytics = build('analyticsreporting', 'v4', credentials=credentials)

  return analytics


def get_report(analytics):
  # Queries the Analytics Reporting API V4.
  # Args: _ analytics _ : An authorized Analytics Reporting API V4 service object.
  # Returns: The Analytics Reporting API V4 response.
  global startDate
  global endDate
  global request1

  return analytics.reports().batchGet(
      body=request1
      ).execute()

def print_response(response):

  # Parses and prints the Analytics Reporting API V4 response.
  # Args: _ response _ : An Analytics Reporting API V4 response.

  for report in response.get('reports', []):
    columnHeader = report.get('columnHeader', {})
    dimensionHeaders = columnHeader.get('dimensions', [])
    metricHeaders = columnHeader.get('metricHeader', {}).get('metricHeaderEntries', [])

    for row in report.get('data', {}).get('rows', []):
      dimensions = row.get('dimensions', [])
      dateRangeValues = row.get('metrics', [])

      for header, dimension in zip(dimensionHeaders, dimensions):
        print(header + ': ', dimension)

      for i, values in enumerate(dateRangeValues):
        for metricHeader, value in zip(metricHeaders, values.get('values')):
          print(metricHeader.get('name') + ':', value)


def main():
  global startDate
  global endDate

  analytics = initialize_analyticsreporting()
  while startDate >= 725:
    response = get_report(analytics)
    print(f'{startDate}daysAgo')
    print_response(response)
    startDate -= 1
    endDate -= 1
  print("Done now, cheers")

if __name__ == '__main__':
  main()

在那个具体的例子中,当它循环时,它会在 request1 中更新 startDate 和 endDate。

目前的输出:

732daysAgo
ga:date:  20181123
ga:sessions: 2887
731daysAgo
ga:date:  20181123
ga:sessions: 2887
730daysAgo
ga:date:  20181123
ga:sessions: 2887
729daysAgo
ga:date:  20181123
ga:sessions: 2887
728daysAgo
ga:date:  20181123
ga:sessions: 2887
727daysAgo
ga:date:  20181123
ga:sessions: 2887
726daysAgo
ga:date:  20181123
ga:sessions: 2887
725daysAgo
ga:date:  20181123
ga:sessions: 2887
Done now, cheers

知道可能是什么问题吗?

【问题讨论】:

  • startDateendDate 这样做时,您不会期望req1 的值会发生某种变化,是吗?您只需使用您的类定义定义一次req1。它不会动态变化;如果你想要它,你必须让它动态构建,然后在每次调用某个函数时返回。
  • 不错的选择 - 我正在尝试让它发挥作用。我现在已将其改回为标准变量,并更新了原始帖子以反映这一点。
  • 这不会改变任何事情; request1 仅在定义时设置,更改 startDateendDaterequest1 的影响仍然为零。
  • 哦,不知道。我将如何动态更改其中的值?正如您可能知道的那样,我对 Python 还是很陌生(除了一些复制和粘贴工作)。我是否必须将其设置为简单函数而不是静态变量?
  • 是的,这就是我所说的“你必须通过动态构建然后在每次调用某个函数时返回”的意思。我将发布一个答案,展示您的函数的外观。

标签: python loops google-analytics global-variables


【解决方案1】:

问题是您希望根据startDateendDate 的值动态生成request1,但您目前只在程序开头定义一次request1,所以它永远不会根据其中任一变量更改其定义。

要让request1 是动态的,您可以创建一个返回请求的函数:

startDate = 732 
endDate = 732
VIEW_ID = 12345678

def get_request1():
    global startDate
    global endDate
    global VIEW_ID
    
    return {
    'reportRequests': 
    [
      {
        'viewId': VIEW_ID,
        'dateRanges': 
        [
          {
            'startDate': f'{startDate}daysAgo',
            'endDate': f'{endDate}daysAgo'
          }
        ],
        'metrics': 
        [
          {
            'expression': 'ga:sessions'
          }
        ],
        'dimensions': 
        [
          {
            'name': 'ga:date'
          }
        ],
        'pageSize': 1
      }
    ]
  }

因此,每次调用get_request1(),其返回值将始终包含当前的开始日期和结束日期。

【讨论】:

  • 传奇。谢谢你。工作很愉快,你帮助我学习了一个我没有向我解释过的基本 Python 概念。有什么办法可以给你小费吗?
  • @PuGZoR 接受我的回答就足够了。很高兴这有帮助。也许你可以通过在未来帮助别人来支付它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-04
  • 1970-01-01
  • 2019-03-19
  • 1970-01-01
  • 2022-09-25
相关资源
最近更新 更多