我试图使用asyncio
的事件循环创建一种对绑定async
方法的计时器回调。现在的问题是绑定的异步方法不应该包含对实例的强引用,否则后者将永远不会被删除。计时器回调应该只和父实例一样长。
我找到了一个解决办法,但我觉得不太好:
import asyncio
import functools
import weakref
class ClassWithTimer:
def __init__(self):
asyncio.ensure_future(
functools.partial(
ClassWithTimer.update, weakref.ref(self)
)()
)
def __del__(self):
print("deleted ClassWithTimer!")
async def update(self):
while True:
await asyncio.sleep(1)
if self() is None: break
print("IN update of object " + repr(self()))
async def run():
foo = ClassWithTimer()
await asyncio.sleep(5)
del foo
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
有没有更好的,更像Python的方法来做这件事?计时器回调确实需要异步。
如果没有asyncio
,weakref.WeakMethod
很可能是一条路。但是asyncio.ensure_future
需要一个协程对象,所以在这种情况下它不起作用。在
根据华左高和格尔曼的回答,我实现了
ensure_weakly_binding_future
,它与ensure_future
基本相同,但没有对绑定方法的实例进行强有力的引用。它不会修改整个绑定(就像基于修饰符的解决方案那样),并在父实例被删除时正确取消未来:对不起,我不知道我是否理解你的问题。这是你要找的解决方案吗?在
输出:
^{pr2}$另一种没有上下文管理器的方法:
几个月前,我遇到了几乎相同的问题,我写了一个装饰师来解决这个问题:
然后,您的代码可以以非常自然的方式重写:
^{pr2}$重要提示:
weakref.proxy
不会阻止您获取强引用。此外,不能保证它的行为与原始对象完全相同。我的实施并没有涵盖所有可能性。
相关问题 更多 >
编程相关推荐