Gio.MemoryInputStream 关​​闭时不释放内存

Posted

技术标签:

【中文标题】Gio.MemoryInputStream 关​​闭时不释放内存【英文标题】:Gio.MemoryInputStream does not free memory when closed 【发布时间】:2018-01-31 23:50:09 【问题描述】:

在 Windows 7 上运行 Python 3.4,Gio.MemoryInputStream 的关闭函数不会像它应该那样释放内存。测试代码是:

from gi.repository import Gio
import os, psutil

process = psutil.Process(os.getpid())

for i in range (1,10) :
    input_stream = Gio.MemoryInputStream.new_from_data(b"x" * 10**7)
    x = input_stream.close_async(2)
    y = int(process.memory_info().rss / 10**6)  # Get the size of memory used by the program
    print (x, y)

这会返回:

True 25
True 35
True 45
True 55
True 65
True 75
True 85
True 95
True 105

这表明在每个循环中,程序使用的内存增加了 10 MB,即使关闭函数返回 True。 一旦 Stream 关​​闭,如何释放内存?

另一个好的解决方案是重用流。但是 set_data 或 replace_data 会引发以下错误: '不支持数据访问方法。改用普通的 Python 属性 很好,但是哪个属性?

我需要 Python 3.4 中的内存流。我用 PyPDF2 创建了一个 Pdf 文件,然后我想用 Poppler 预览它。由于 Poppler 中的一个错误(请参阅 Has anyone been able to use poppler new_from_data in python?),我无法使用 new_from_data 函数并想使用 new_from_stream 函数。

【问题讨论】:

【参考方案1】:

这是a bug in GLib’s Python bindings,无法轻易修复。

相反,您应该使用g_memory_input_stream_new_from_bytes(),它以不同方式处理释放内存,并且不应该遇到相同的错误。


更详细地说,new_from_data() 的错误是由 introspection annotations 引起的,GLib 使用它来允许语言绑定自动公开其所有 API,不支持 new_from_data()GDestroyNotify 参数,这需要设置为非NULL 函数以释放分配给其他参数的内存。在gdb 下运行脚本表明pygobject 将NULL 传递给GDestroyNotify 参数。它再好不过了,因为目前还没有办法表达data 参数的内存管理语义取决于传递给destroy 的内容。

【讨论】:

【参考方案2】:

感谢您的回答,@Philip Withnall。我测试了您提出的解决方案,并且有效。为了帮助其他人理解,这是我的测试代码:

from gi.repository import Gio, GLib
import os, psutil

process = psutil.Process(os.getpid())

for i in range (1,10) :
    input_stream = Gio.MemoryInputStream.new_from_bytes(GLib.Bytes(b"x" * 10**7))
    x = input_stream.close()
    y = int(process.memory_info().rss / 10**6)  # Get the size of memory used by the program
    print (x, y)

现在 y 不再增长。

【讨论】:

以上是关于Gio.MemoryInputStream 关​​闭时不释放内存的主要内容,如果未能解决你的问题,请参考以下文章

eclipse异常关了,tomcat如何关

《Web应用开发》(头歌)

ipad蓝牙怎么关?

Python语法基础实验闯关

全民飞机大战第二十三关怎么过 过关攻略

sql-lib闯关秘籍之61-65关