在Python中以最优方式向JSON追加数据(考虑内存限制)

1 投票
2 回答
2817 浏览
提问于 2025-04-16 09:26

我正在尝试找到一种最佳方法,用Python将一些数据追加到一个json文件中。简单来说,我大约有100个线程在同时运行,存储数据到一个数组中。当它们完成后,会使用json.dump将数据发送到json文件。然而,由于这个数组的构建可能需要几个小时,最终我会耗尽内存。所以我想看看在这个过程中,怎样才能使用最少的内存。以下是我目前的做法,但它消耗了太多内存。

        i               = 0
        twitter_data    = {}
        for null in range(0,1):
            while True:
                try:
                    for friends in Cursor(api.followers_ids,screen_name=self.ip).items():
                        twitter_data[i]                     = {}
                        twitter_data[i]['fu']               = self.ip
                        twitter_data[i]['su']               = friends
                        i = i + 1
                except tweepy.TweepError, e:
                    print "ERROR on " + str(self.ip) + " Reason: ", e
                    with open('C:/Twitter/errors.txt', mode='a') as a_file:
                        new_ii = "ERROR on " + str(self.ip) + " Reason: " + str(e) + "\n"
                        a_file.write(new_ii)
                break

        ## Save data

        with open('C:/Twitter/user_' + str(self.id) + '.json', mode='w') as f:
                json.dump(twitter_data, f, indent=2, encoding='utf-8')

谢谢

2 个回答

3

逐个输出每个项目,像创建数组一样,同时手动为这个数组添加JSON格式。JSON是一种简单的格式,所以这很容易做到。

下面是一个简单的例子,它会打印出一个JSON数组,而不需要把所有内容都放在内存里;只需要一次存储数组中的一个元素就可以了。

def get_item():
    return { "a": 5, "b": 10 }

def get_array():
    results = []
    yield "["
    for x in xrange(5):
        if x > 0:
            yield ","
        yield json.dumps(get_item())
    yield "]"

if __name__ == "__main__":
    for s in get_array():
        sys.stdout.write(s)
    sys.stdout.write("\n")
1

我来分享一下我的看法,基于Glenn的回答,但这里我会按照提问者的要求,把一个大的字典序列化,并且使用更符合Python风格的enumerate,而不是手动增加i的值(如果有错误,可以单独记录错误的数量,然后在写入f之前从i中减去这个数量):

with open('C:/Twitter/user_' + str(self.id) + '.json', mode='w') as f:
   f.write('{')
   for i, friends in enumerate(Cursor(api.followers_ids,screen_name=self.ip).items()):
        if i>0:
            f.write(", ")
        f.write("%s:%s" % (json.dumps(i), json.dumps(dict(fu=self.ip, su=friends))))
   f.write("}")

撰写回答