通过大型JSON文件高效循环

时间:2017-09-29 14:57:20

标签: python json

我编写了一个简短的python脚本,用于从API中提取一些填充数据并将其存储到csv中。可以找到API返回的示例here。 “数据”包含8000多个观察结果,因此我正在寻找一种有效的方法来访问它。我写的代码正在运行,但需要几个小时才能运行。 因此,我的问题是,有没有办法更有效地循环这个JSON,或者在没有遍历每个观察的情况下提取所需的数据?

import requests 
api_base = "http://dw.euro.who.int/api/v3/data_sets/HFAMDB/HFAMDB_8"

with open("population.csv", "w") as outfile:
   outfile.write("country,year,group,fullname,count\n")
   for i in range(32,51):
      response = requests.get(api_base+str(i))
      print(api_base+str(i))
      for observation in response.json()['data']:
          count = observation["value"]["numeric"]
          country = observation["dimensions"]["COUNTRY"]
          year = observation["dimensions"]["YEAR"]
          group = observation["dimensions"]["AGE_GRP_6"]
          fullGroupName = response.json()['full_name']
          if observation["dimensions"]["SEX"] == "ALL":
              outfile.write("{},{},{},{},{}\n".format(country, year, group, fullGroupName, count))

提前感谢您的回答。

3 个答案:

答案 0 :(得分:2)

不要不必要地一遍又一遍地打电话给response.json()

而不是

  for observation in response.json()['data']:
      fullGroupName = response.json()['full_name']

DO

  data = response.json()
  for observation in data['data']:
      fullGroupName = data['full_name']

在这个改变之后,整个事情需要我的电脑大约33秒。几乎所有这些都是针对请求的。也许你可以通过使用并行请求来进一步提高速度,如果网站没问题的话。

答案 1 :(得分:1)

虽然Stefan Pochmann已经回答了你的问题,但我认为值得一提的是你如何能够找出问题所在。

一种方法是使用分析器,例如Python的cProfile,它包含在标准库中。

假设您的脚本名为slow_download.py,您可以将循环中的范围限制为range(32, 33),并按以下方式执行:

python3 -m cProfile -s cumtime slow_download.py

-s cumtime按累计时间对呼叫进行排序。

结果将是:

   http://dw.euro.who.int/api/v3/data_sets/HFAMDB/HFAMDB_832
          222056 function calls (219492 primitive calls) in 395.444 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    122/1    0.005    0.000  395.444  395.444 {built-in method builtins.exec}
        1   49.771   49.771  395.444  395.444 py2.py:1(<module>)
     9010    0.111    0.000  343.904    0.038 models.py:782(json)
     9010    0.078    0.000  332.900    0.037 __init__.py:271(loads)
     9010    0.091    0.000  332.801    0.037 decoder.py:334(decode)
     9010  332.607    0.037  332.607    0.037 decoder.py:345(raw_decode)
     ...

这清楚地表明问题与json()及相关方法有关:loads()raw_decode()

答案 2 :(得分:0)

如果数据非常大,请将数据转储到mongodb中,并有效地查询任何内容。