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

时间:2017-08-23 11:47:15

标签: python gio

在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,即使close函数返回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函数。

2 个答案:

答案 0 :(得分:4)

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

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

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

答案 1 :(得分: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)

现在你不再长大。