python - 生成数百万 json 数据
python - generating millions of json data
我需要一些 json 格式的虚拟数据,以便在另一个项目中使用。我目前在下面的代码中使用 Faker
包:
from json import dumps
from faker import Faker
import collections
database = []
filename = '1M'
length = 1000000
fake = Faker() # <--- Forgot this
for x in range(length):
database.append(collections.OrderedDict([
('last_name', fake.last_name()),
('first_name', fake.first_name()),
('street_address', fake.street_address()),
('email', fake.email())
]))
with open('%s.json' % filename, 'w') as output:
output.write(dumps(database, indent=4))
print "Done."
此代码有效,但速度很慢。我尝试了 PyPy
,结果令我震惊。我目前能够在大约 600 秒内生成一个包含 100 万数据的 json 文件,大约 220mb。问题是当我尝试更进一步时,例如,200 万个数据,我希望它在 ~1200 秒内完成,脚本运行超过这个时间,我收到这个异常 MemoryError
没有关于它发生的原因的解释,我相信它与 PYPY_GC_MAX
有关,但是一个 2M 的文件应该重 ~440mb。
在尝试解决此问题时,我仍在寻找一种方法来进一步压缩生成时间。我已经尝试过列表理解,map()
,结果与 for 循环相同。
谢谢
而不是 output.write(json.dumps(database))
,使用 json.dump(database, output)
迭代地将 JSON 写入文件,而无需在内存中构建大字符串。
你内存不足是因为你首先生成了整个数据库,然后转储了数据库。一种对内存更友好的方法是动态生成字典条目。更好的方法是使用 generator 来动态输入条目。
def fake_person_generator(length):
for x in range(length): # xrange in Python 2.7
yield OrderedDict([
('last_name', 'lastname_%i' % x),
('first_name', 'firstname_%i' % x),
('street_address', 'adress_%i' % x),
('email', 'email_%i' % x)])
结合 Alex Hall 的回答,这应该会显着减少内存需求。
我不太了解 json-模块,但写作应该是这样的:
length = 1000000
fpg = fake_person_generator(length)
with open('%s.json' % filename, 'w') as output:
for person in fpg:
json.dump(person, output)
print "Done."
您不需要使用 OrderedDict
: JSON 格式可能不会(也不会)保存项目的顺序。即使订单将保存在文件中 - 当另一个项目解析该文件时它也会中断。
你只需要使用dict
。而且速度会快很多。
要保存项目的顺序,您应该明确保留每个元素的索引。像这样:
from json import dumps
from faker import Faker
import collections
import json
def fake_person_generator(length, fake):
for x in range(length): # xrange in Python 2.7
yield {'last_name': fake.last_name(),
'first_name': fake.first_name(),
'street_address': fake.street_address(),
'email': fake.email(),
'index': x}
database = []
filename = '1M'
length = 1000000
fake = Faker() # <--- Forgot this
fpg = fake_person_generator(length, fake)
with open('%s.json' % filename, 'w') as output:
output.write('[') # to made json file valid according to JSON format
for person in fpg:
json.dump(person, output)
output.write(']') # to made json file valid according to JSON format
print "Done."
我需要一些 json 格式的虚拟数据,以便在另一个项目中使用。我目前在下面的代码中使用 Faker
包:
from json import dumps
from faker import Faker
import collections
database = []
filename = '1M'
length = 1000000
fake = Faker() # <--- Forgot this
for x in range(length):
database.append(collections.OrderedDict([
('last_name', fake.last_name()),
('first_name', fake.first_name()),
('street_address', fake.street_address()),
('email', fake.email())
]))
with open('%s.json' % filename, 'w') as output:
output.write(dumps(database, indent=4))
print "Done."
此代码有效,但速度很慢。我尝试了 PyPy
,结果令我震惊。我目前能够在大约 600 秒内生成一个包含 100 万数据的 json 文件,大约 220mb。问题是当我尝试更进一步时,例如,200 万个数据,我希望它在 ~1200 秒内完成,脚本运行超过这个时间,我收到这个异常 MemoryError
没有关于它发生的原因的解释,我相信它与 PYPY_GC_MAX
有关,但是一个 2M 的文件应该重 ~440mb。
在尝试解决此问题时,我仍在寻找一种方法来进一步压缩生成时间。我已经尝试过列表理解,map()
,结果与 for 循环相同。
谢谢
而不是 output.write(json.dumps(database))
,使用 json.dump(database, output)
迭代地将 JSON 写入文件,而无需在内存中构建大字符串。
你内存不足是因为你首先生成了整个数据库,然后转储了数据库。一种对内存更友好的方法是动态生成字典条目。更好的方法是使用 generator 来动态输入条目。
def fake_person_generator(length):
for x in range(length): # xrange in Python 2.7
yield OrderedDict([
('last_name', 'lastname_%i' % x),
('first_name', 'firstname_%i' % x),
('street_address', 'adress_%i' % x),
('email', 'email_%i' % x)])
结合 Alex Hall 的回答,这应该会显着减少内存需求。
我不太了解 json-模块,但写作应该是这样的:
length = 1000000
fpg = fake_person_generator(length)
with open('%s.json' % filename, 'w') as output:
for person in fpg:
json.dump(person, output)
print "Done."
您不需要使用 OrderedDict
: JSON 格式可能不会(也不会)保存项目的顺序。即使订单将保存在文件中 - 当另一个项目解析该文件时它也会中断。
你只需要使用dict
。而且速度会快很多。
要保存项目的顺序,您应该明确保留每个元素的索引。像这样:
from json import dumps
from faker import Faker
import collections
import json
def fake_person_generator(length, fake):
for x in range(length): # xrange in Python 2.7
yield {'last_name': fake.last_name(),
'first_name': fake.first_name(),
'street_address': fake.street_address(),
'email': fake.email(),
'index': x}
database = []
filename = '1M'
length = 1000000
fake = Faker() # <--- Forgot this
fpg = fake_person_generator(length, fake)
with open('%s.json' % filename, 'w') as output:
output.write('[') # to made json file valid according to JSON format
for person in fpg:
json.dump(person, output)
output.write(']') # to made json file valid according to JSON format
print "Done."