如何做到清除的可靠蟒蛇?
-
20-08-2019 - |
题
我有一些ctypes绑定,并为每一个体。新的我应该叫体。免费的。图书馆我要结合不必分配程序的绝缘出的其余部分的代码(他们可以被称为有关的任何地方存在),并使用几个有用的功能我需要循环的参考。
我认为这将会解决如果我找到一个可靠的方式挂钩析构的一个对象。(weakrefs会的帮助,如果他们想让我只是回调 之前 数据是下降了。
所以很明显这个代码megafails当我把velocity_func:
class Body(object):
def __init__(self, mass, inertia):
self._body = body.New(mass, inertia)
def __del__(self):
print '__del__ %r' % self
if body:
body.Free(self._body)
...
def set_velocity_func(self, func):
self._body.contents.velocity_func = ctypes_wrapping(func)
我还试图解决它通过weakrefs,与那些东西似乎越来越只是更糟的是,仅仅在很大程度上更加不可预测。
甚至如果我不把在velocity_func,会出现周期至少然后当我这样做:
class Toy(object):
def __init__(self, body):
self.body.owner = self
...
def collision(a, b, contacts):
whatever(a.body.owner)
因此,如何确定的结构将得到垃圾收集,即使它们是分配/被释放的公共图书馆?
有的仓库,如果你有兴趣了解更多的细节: http://bitbucket.org/cheery/ctypes-chipmunk/
解决方案 3
如果weakrefs未破,我想这可能工作:
from weakref import ref
pointers = set()
class Pointer(object):
def __init__(self, cfun, ptr):
pointers.add(self)
self.ref = ref(ptr, self.cleanup)
self.data = cast(ptr, c_void_p).value # python cast it so smart, but it can't be smarter than this.
self.cfun = cfun
def cleanup(self, obj):
print 'cleanup 0x%x' % self.data
self.cfun(self.data)
pointers.remove(self)
def cleanup(cfun, ptr):
Pointer(cfun, ptr)
我还没有尝试。在重要的部分是指针没有外国指针任何强引用,除了一个整数。如果ctypes不会处理,我应该与绑定释放空闲内存这应该工作。是的,这basicly一个黑客,但我认为这可能比以前的事情,我一直在努力更好地工作。
编辑:试了一下,似乎小后上班微调我的代码。一个令人惊讶的事情是,即使我的删除出从我所有的结构,它似乎仍然会失败。有趣的,但令人沮丧。
无论是作品,从一些怪异的机会,我已经能够在地方离席循环引用,但事情留破产了。
编辑:嗯.. weakrefs WERE毕竟碎了!所以有可能对于在python可靠清理无解,除了不是迫使它是显式的。
其他提示
你想要做什么,那就是创建一个分配的事情,然后当对象不再使用自动重新分配,是几乎不可能在Python的对象,很遗憾。在删除声明不能保证被调用,所以你不能依靠这一点。
在Python的标准方法是简单地:
try:
allocate()
dostuff()
finally:
cleanup()
或者因为2.5还可以创建上下文管理者和with语句,这是这样做的一个更合适的方法使用。
但是这两种主要当你在一个代码段的开始分配/锁。如果你想有分配方案的整个运行的东西,你需要在启动时分配的资源,该方案的主要代码运行之前,事后解除分配。还有这里没有涉及一种情况,那就是当你想分配和动态解除分配的资源,并在代码中的许多地方使用它们。例如你想要的内存缓冲区或类似的游泳池。但大多数的情况下是内存,Python会为你处理,所以你不必理会那些。还有的地方,你想拥有的东西,不是动态内存池分配过程的情况下,然后你会希望你在你的例子尝试释放的类型,而是的棘手与Python做
在CPython, __del__
是 一个可靠析构的对象,因为它总是会被称为当参考数达到零(注:有可能的情况下-喜欢圆形引用的项目 __del__
定义的方法-这里的参数将永远不会达到零,但这是另外一个问题)。
更新
从评论,我理解这个问题有关的是为破坏对象: 身体 是一个全球性的目的,及正在销毁之前,所有其他目的,因此它不再是提供给他们。
实际上,采用全球对象不好;这不仅是因为问题这样的一个,而且还因为维护。
然后我会改变你的类的东西喜欢这个
class Body(object):
def __init__(self, mass, inertia):
self._bodyref = body
self._body = body.New(mass, inertia)
def __del__(self):
print '__del__ %r' % self
if body:
body.Free(self._body)
...
def set_velocity_func(self, func):
self._body.contents.velocity_func = ctypes_wrapping(func)
几个注:
- 变化是仅仅增加一个参考的全球 身体 对象,因此将生活至少作为所有对象都来自这一类。
- 仍然,使用全球对象是不好的,因为单元测试和维护;更好的是将有一家工厂的目的,将设置正确的"体"的类,并在情况单元的测试将很容易把一种嘲笑的对象。但是这是真的你和多少努力你觉得有意义在这个项目。