更高效的解析和处理大文件的JSON对象的方法

1 投票
1 回答
1377 浏览
提问于 2025-04-18 12:52

下面的代码怎么优化?(用Python可以吗,还是应该换个工具?)

这是我在Stack Overflow上问过的最疯狂的问题,但我想试试,希望能得到一些建议,看看我是否在用正确的工具和方法来高效处理大量数据。我并不一定在寻找代码优化的帮助,除非我完全忽略了什么,但我主要想知道是否应该完全换个框架,而不是继续用Python。我对Python还不够熟悉,不太确定是否能更高效地处理大量数据并存储到数据库中。

下面的实现代码是用来读取一个目录中的文本文件:

  • 每个文本文件里有5万行的JSON对象……
  • 这些对象需要被解析、读取,然后转换成CSV格式,最后再加载到数据库中。
  • 我不喜欢使用列表容器,希望能找到其他方法在Python中实现这个功能,做得更好。我最初的想法是应该使用生成器,但还不太确定。
  • 最后的那个疯狂的连接部分很重要,因为它把用逗号分隔的列表转换成了自己的行。 将用字符串分隔的列转换为行

代码:

  triggerZipFiles = glob.glob('*.zip')
  for triggerFiles in triggerZipFiles:
      with zipfile.ZipFile(triggerFiles, 'r') as myzip:
          for logfile in myzip.namelist():
              datacc = []
              zipcc = []
              csvout = '{}_US.csv'.format(logfile[:-4])
              f = myzip.open(logfile)
              contents = f.readlines()
              for line in contents:
                  try:
                      parsed = json.loads(line[:-2])
                      if "CC" in parsed['data']['weatherType'] and "US" in parsed['zipcodes']:
                          datacc.append(parsed['data'])
                          zipcc.append(parsed['zipcodes'])
                  except:
                      pass
              if len(datacc) > 0:
                  df = pd.concat([pd.DataFrame(zipcc), pd.DataFrame(datacc)], axis=1)
                  df = pd.concat((pd.Series((v, row['key'], row['key'], row['key'],
                    row['key'], row['key'], row['key'], row['key'], row['key'],
                    row['key'], row['key'], row['key'], row['key'], row['key'],
                    row['key'], row['key'], row['key'], row['key'], row['key'],
                    row['key'], row['key'], row['key'], row['key'], row['key'],
                    row['key'], row['key'], row['key'], row['key'],
                    row['key'], row['key'], row['key'], row['key'],
                    row['key'], row['key'], row['key'], row['key'],
                    row['key'], row['key'], row['key'], row['key'], row['key'],
                    row['key'], row['key'], row['key'], row['key'],
                    row['key'], row['key'], row['key'], row['key'], row['key'],
                    row['key'], row['key'], row['key'], row['key'], row['key'], row['key'],
                    row['key'], row['key'], row['key'], row['key'], row['key'], row['key'],
                    row['key'], row['key'], row['key'], row['key'], row['key'], row['key'],
                    row['key'], row['key'], row['key'], row['key']), df.columns) for _,
                      row in df.iterrows() for v in row['US']), axis=1).T                
                  df.to_csv(csvout, header=None, index=False)
              else:
                  pass
              print datetime.now().strftime('%Y/%m/%d %H:%M:%S') + ": Finished: {}".format(logfile)

1 个回答

3

首先,行数在处理json时并不是一个特别有用的指标!
其次,你的想法是对的:确实应该分块处理(分别读取、清理和保存每一部分)。

我建议使用pandas的read_json函数,这样在创建数据框时效率更高(它不会创建一个临时的python字典),可以参考文档中的读取json部分

  • 如果它们实际上并不是真正的json,那么通过字符串处理把它们变成json通常是最好的办法。
  • 如果你有“形状奇怪”的json,那么在读取时可以使用json_normalize,或者在读取数据框后解析那些包含多个列的列(比如使用Series的字符串方法或apply)。

*实际格式不太清楚,但通常只需稍微处理一下就能变成有效的json。

Python小贴士:如果你的缩进层级超过几层,考虑把它拆分成更多的函数。(这里显而易见的选择是有f1(logfile)f2(line),但使用描述性的名称会更好...)

撰写回答