【问题标题】:Opening A large JSON file in Python with no newlines for csv conversion Python 2.6.6在 Python 中打开一个大型 JSON 文件,没有用于 csv 转换的换行符 Python 2.6.6
【发布时间】:2014-03-10 23:24:45
【问题描述】:

我正在尝试将一个非常大的 json 文件转换为 csv。我已经能够将这种类型的小文件转换为 10 条记录(例如)csv 文件。但是,当尝试转换大文件(csv 文件中大约 50000 行)时,它不起作用。数据由 curl 命令创建,其中 -o 指向要创建的 json 文件。输出的文件中没有换行符。 csv 文件将使用 csv.DictWriter() 写入,并且(其中 data 是 json 文件输入)具有以下形式

rowcount = len(data['MainKey'])
colcount = len(data['MainKey'][0]['Fields'])

然后我循环遍历行和列的范围以获取 csv 字典条目

csvkey = data['MainKey'][recno]['Fields'][colno]['name']
cvsval = data['MainKey'][recno][['Fields'][colno]['Values']['value']

我尝试使用其他问题的答案,但它们不适用于大文件 (du -m bigfile.json = 157),而且我要处理的文件更大。

尝试获取每行显示的大小

myfile = open('file.json','r').
line = readline():
print len(line)

表明这会将整个文件作为完整字符串读取。因此,一个小文件将显示 67744 的长度,而一个较大的文件将显示 163815116。

尝试直接从

读取数据
data=json.load(infile)

给出其他问题针对大文件讨论过的错误

尝试使用

def json_parse(self, fileobj, decoder=JSONDecoder(), buffersize=2048):


  yield results

another answer 所示,适用于 72 kb 文件(10 行,22 列),但对于 157 mb 的中等大小文件(来自 du -m bigfile .json)

请注意,调试打印显示每个块的大小为 2048,由默认输入参数指定。它似乎试图以 2048 个块遍历整个 163815116(从上面的 len 显示)。如果我将块大小更改为 32768,简单的数学运算表明,处理该文件需要 5,000 个循环。

将块大小更改为 524288 大约每 11 个块退出循环,但仍需要大约 312 个块来处理整个文件

如果我可以让它在每个行项目的末尾停止,我将能够处理该行并根据下面显示的表单将其发送到 csv 文件。

小文件上的vi显示它的形式是

{"MainKey":[{"Fields":[{"Value": {'value':val}, 'name':'valname'}, {'Value': {'value':val}, 'name':'valname'}}], (other keys)},{'Fields' ... }] (other keys on MainKey level) }

我不能使用 ijson,因为我必须为无法导入其他软件的系统设置它。

【问题讨论】:

  • open('file.json','r').readline() 返回一行,然后for 循环遍历该行的各个字符。
  • @MartijnPieters 说的!
  • 如果无法访问您的bigfile.json,我们无法说出为什么我之前的答案对您不起作用。文件中各个不同的 JSON 条目有多大?也许你应该在我的函数中添加一个print 语句来显示缓冲区有多大?在buffer += chunk 之后添加print('buffer size now', len(buffer)) 以查看文件“挂起”时从文件中读取了多少。
  • 感谢您指出块大小问题。似乎 python 能够使用 8388606 的块大小一次处理 1000 行,但如果可能的话,我仍然想找到一种更有效的处理方式。

标签: python json csv


【解决方案1】:

我最终使用了 8388608(0x800000 十六进制)的块大小来处理文件。然后我处理作为循环的一部分读入的行,保持处理的行数和丢弃的行数。在每个流程函数中,我将数字添加到总数中,以便跟踪处理的总记录。

这似乎是它需要走的路。

下次问这样的问题时,请强调必须指定大块大小,而不是原始答案中显示的 2048。

循环继续

first = True
for data in self.json_parse(inf):
  records = len(data['MainKey'])
  columns = len(data['MainKey'][0]['Fields'])
  if first:
    # Initialize output as DictWriter
    ofile, outf, fields = self.init_csv(csvname, data, records, columns)
    first = False
  reccount, errcount = self.parse_records(outf, data, fields, records)

在解析例程中

for rec in range(records):
  currec = data['MainKey'][rec]
  # If each column count can be different
  columns = len(currec['Fields'])
  retval, valrec = self.build_csv_row(currec, columns, fields)

要解析列使用

for col in columns:
  dataname = currec['Fields'][col]['name']
  dataval = currec['Fields'][col]['Values']['value']

因此,引用现在可以正常工作并且可以正确处理处理。大块显然允许处理足够快以处理数据,同时足够小而不会使系统过载。

【讨论】:

    猜你喜欢
    • 2018-07-14
    • 2018-10-22
    • 1970-01-01
    • 1970-01-01
    • 2017-01-29
    • 1970-01-01
    • 1970-01-01
    • 2015-01-13
    • 1970-01-01
    相关资源
    最近更新 更多