Skip to main content
 首页 » 编程设计

python之在 Python 中打开一个没有换行符的大型 JSON 文件进行 csv 转换 Python 2.6.6

2025年05月04日10emanlee

我正在尝试将一个非常大的 json 文件转换为 csv。我已经能够将这种类型的小文件转换为 10 条记录(例如)csv 文件。但是,当尝试转换大文件(csv 文件中大约 50000 行)时,它不起作用。数据是通过 curl 命令创建的,其中 -o 指向要创建的 json 文件。输出的文件中没有换行符。 csv 文件将使用 csv.DictWriter() 编写,并且(其中数据是 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)似乎要么锁定要么花费无穷无尽的时间

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

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

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

小文件上的vi显示是这样的形式

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

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

请您参考如下方法:

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

这似乎是它需要走的路。

下次问这样的问题时,请强调必须指定大块大小,而不是原始答案中显示的 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'] 

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