Python 生成器实现并没有减少内存消耗

问题描述 投票:0回答:1

我有三个 json.gz 文件。这三个文件包含按不同 ID 分组的不同数据(餐厅、菜单和匹配项)。我必须读取所有这些文件,并使用这三个文件中的相应数据按 Id 创建新的 json 文件。我有一台虚拟机,运行代码时有一些内存限制。

一开始,我将这三个文件合并到三个 json 对象中,然后用普通的 for 循环迭代它们。使用此解决方案,我的代码消耗了虚拟机的大量内存,因为我正在加载整个数据。

我意识到我只需要特定 Id 的数据来创建最终的 json 文件,并且我不应该同时加载所有 Id 的所有数据。因此,我认为 Python 生成器将是这种情况下的解决方案。我创建了以下代码:

from json import loads

def load_data_set(string_restaurants_data: str,
                  string_menus_data: str,
                  string_matchings_data: str,): 


  menus_data = loads(string_menus_data)   
  matchings_data = loads(string_matchings_data)   
  restaurants_data = loads(string_restaurants_data)
  
  for id, menu_data in menus_data.items():
    yield id, restaurants_data[id], menu_data, matchings_data[id] if id in matchings_data else "{}"



def main():
    '''
    some code to read the json.gz files. The data is stored in these three string variables: string_restaurants_data, string_menus_data and string_matchings_data
    '''

    restaurants_data_set = load_data_set(string_restaurants_data,
                                             string_menus_data,
                                             string_matchings_data)
    
    size_generator = sys.getsizeof(restaurants_data_set)

    del string_menus_data
    del string_restaurants_data
    del string_matchings_data
    gc.collect()

    list_result = {}
    for restaurant in restaurants_data_set:
      result_data = aggregate_menu_data(restaurant[0],
                                        dumps(restaurant[2]),
                                        dumps(restaurant[1]),
                                        dumps(restaurant[3]),
                                        string_parameters,
                                        eval(debug))
    

      list_result.update(result_data)
    
    data['result'] = dumps(list_result)
     

我检查了虚拟机中的任务管理器,与之前没有生成器的版本相比,我没有看到内存消耗显着减少。谁能告诉我我是否正确实现了 python 生成器来解决我的需求?或者有没有更好的方法只在内存中加载我创建json文件所需的数据而不影响速度?

Python版本:3.11

python generator
1个回答
0
投票

不,你的生成器不会在这里做任何事情,因为你已经加载了 3 个字典。由于您是用 3 个单独的文件构建

restaurants_data_set
,因此生成器在这种情况下并没有真正的帮助。

有什么理由不能只使用数据库吗?它是为此类事情而构建的,并且效率更高。


首先,不要将文件读入字符串并用

json.loads
解析它们,因为你最终会在内存中得到 both 完整的字符串和字典。在文件对象上使用
json.load(f)
可以绕过第一步。

然后,如果您单独处理文件并在处理过程中构建结果,则可以避免在任何一点将多个文件加载到内存中。

restaurants_data_set = {}
with open(string_menus_path, 'r') as f:
    for id, menu_data in json.load(f).items():
        restaurants_data_set[id] = [None, menu_data '"{}"']
with open(string_restaurants_path, 'r') as f:
    for id, restaurant_data in json.load(f).items():
        restaurants_data_set[id][0] = restaurant_data
with open(string_matchings_path, 'r') as f:
    for id, matchings_data in json.load(f).items():
        restaurants_data_set[id][2] = matchings_data

for id, (restaurant_data, menu_data, matchings_data) in restaurants_data_set.items():
    ...

对于更高级的东西,您可以尝试以块的形式读取 json 数据。

© www.soinside.com 2019 - 2024. All rights reserved.