【问题标题】:Cleaning memory after loading data from a JSON从 JSON 加载数据后清理内存
【发布时间】:2011-09-20 18:01:42
【问题描述】:

我正在加载一个 JSON 文件以对其进行解析并将其(仅 JSON 的一部分)转换为 CSV。 因此,在方法结束时,我将释放已加载 JSON 的空间。

方法如下:

def JSONtoCSV(input,output):
   outputWriter = csv.writer(open(output,'wb'), delimiter=',')
   jsonfile = open(input).read()
   data = loads(jsonfile)

   for k,v in data["specialKey"].iteritems():
      outputWriter.writerow([v[1],v[5]])

如何释放“数据”变量的空间?

【问题讨论】:

    标签: python json


    【解决方案1】:

    在 Python 中,变量超出范围时会自动释放,因此您不必担心。但是,如果你真的想要,你可以使用

    del data
    

    需要注意的一点是垃圾收集器可能不会立即启动,即使您确实使用了del。这就是垃圾收集的缺点。您只是没有 100% 的内存管理控制权。如果你想使用 Python,这是你需要接受的。你只需要相信垃圾收集器就知道它在做什么。

    【讨论】:

    • del 是语句而不是函数——括号不是必需的。
    • 另外,当计数达到零时,引用计数会立即释放内存——它独立于循环引用等的垃圾收集过程。
    • 使用del不仅意味着GC不会立即启动(准备收集的东西的时间因Python实现而异),它并不意味着对象的名称本来就可能被收集起来。
    【解决方案2】:

    数据变量不占用任何有意义的空间——它只是一个名称。数据 object 占用了一些空间,Python 不允许您手动释放对象。对象将在没有引用它们的一段时间后被垃圾回收。

    为确保您不会让事物保持比您想要的时间更长,请确保您没有访问它们的方法(没有仍然绑定到它们的名称等)。

    一个改进的实现可能是

    def JSONtoCSV(input_filename, output_filename):
        with open(input_filename) as f:
            special_data = json.load(f)[u'specialKey']
    
        with open(output_filename,'wb') as f:
            outputWriter = csv.writer(f, delimiter=',')
            for k, v in special_data.iteritems():
                outputWriter.writerow([v[1], v[5]])
    

    这永远不会存储您称为jsonfile 的字符串或您称为data 的字典,因此它们可以在Python 需要时立即被收集。前一种改进是通过使用json.load 而不是json.loads 进行的,后者采用文件对象本身。后一种改进是通过立即查找 'specialKey' 而不是将名称绑定到所有 data 来实现的。

    请考虑一下,这种微妙的舞蹈可能根本没有必要,因为一旦您返回这些参考将不再存在,而您充其量只是暂时加快了速度。

    【讨论】:

      【解决方案3】:
      del data
      

      如果你只有一个参考,应该这样做。请记住,当当前作用域结束(函数返回)时,这将自动发生。

      另外,你不需要保留jsonfile 字符串,你可以

      data = json.load(open(input))
      

      直接从文件中读取 JSON 数据。

      如果您希望 data 在完成后立即消失,您可以将所有这些结合起来:

      for k,v in json.load(open(input))["specialKey"].iteritems():
      

      由于一旦循环结束就没有对数据的引用,Python 将立即释放内存。

      【讨论】:

      • 谢谢,但即使我删除了变量,它也没有释放空间
      • @Oto 你试过我最后的建议了吗?另外,您确定有必要担心吗?在您知道确实存在问题之前不要进行优化。
      • 它应该是免费的(如空)。它仍然被分配给解释器并且可能被重用。 IIRC
      • I@agf 我没有尝试您的建议,因为我省略了一行代码,其中我在循环之前使用了 data 变量。
      • @rpInt 所以空间是由python分配的,但它是空闲空间?
      【解决方案4】:

      Python 是一种垃圾回收语言,因此您不必担心一旦使用它就会释放内存;一旦jsonfile 变量超出范围,它会被解释器自动释放。

      如果你真的想删除变量,可以使用del jsonfile,删除后尝试引用会报错。但是,除非您加载的数据足以导致性能显着下降,否则我会将其留给垃圾收集器。

      【讨论】:

      • 当我调用这个方法时,即使方法完成它也不会释放空间
      • 垃圾收集和引用计数实际上是 Python 中的两种不同机制——在大多数情况下,是引用计数释放内存,而不是垃圾收集。
      • @Oto - 等等,你想删除文件吗?这与释放内存有很大不同。
      • @agf - 引用计数在技术上是垃圾收集的一种形式。
      • 一般意义上是可以的,但是对于 CPython,垃圾回收是一个特定的可选过程,与引用计数分开。
      【解决方案5】:

      请参考Python json memory bloat。由于未达到阈值,因此不会启动垃圾收集。所以即使是 del 调用也不会释放内存。然而,使用 gc.collect() 强制垃圾回收将释放对象。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-21
        • 2012-06-14
        相关资源
        最近更新 更多