如何解决在__del __
我想定义本质上是关闭资源的异步__del__
。这是一个例子。
import asyncio
class Async:
async def close(self):
print('closing')
return self
def __del__(self):
print('destructing')
asyncio.ensure_future(self.close())
async def amain():
Async()
if __name__ == '__main__':
asyncio.run(amain())
这可行,可以按预期打印destructing
和closing
。但是,如果资源是在异步函数外部定义的,则会调用__del__
,但永远不会执行关闭操作。
def main():
Async()
此处未发出警告,但打印件显示未完成关闭。如果已运行异步功能,但在其外部创建了任何实例,则会发出警告 。
def main2():
Async()
asyncio.run(amain())
RuntimeWarning:从未等待协程'Async.close'
这是1和2中的主题,但都没有我想要的东西,或者也许我不知道如何看。特别是第一个问题是有关删除资源的问题,答案是使用asyncio.ensure_future
进行了建议,上面已经测试过。使用更新的asyncio.create_task
的Python文档suggests,但在非异步情况下,它会直接引发错误,因为没有当前循环。我最后的绝望尝试是使用asyncio.run
,它适用于非异步情况,但不适用于异步情况,因为在已经有一个线程的线程中调用run
是prohibited。运行循环。此外,文档指出,应该在程序中只能被调用一次。
我还是异步事物的新手。如何实现?
用例一词,因为在注释中提到异步上下文管理器是首选方法。我同意,将它们用于短期资源管理将是理想的。但是,由于两个原因,我的用例有所不同。
- 该类的用户不一定知道基础资源。最好对不喜欢资源本身的用户隐藏隐藏资源的资源。
- 需要在同步上下文中实例化该类(或使其可以实例化),并且通常只创建一次。例如,在Web服务器上下文中,将在全局范围内实例化该类,然后在端点定义中使用其异步功能。
例如:
asc = Async()
server.route('/','GET')
async def root():
return await asc.do_something(),200
我对实现这种功能的其他建议持开放态度,但是在这一点上,即使我对可能性的好奇心也足以做到这一点,这足以让我想要回答这个特定问题,而不仅仅是一般的问题。
解决方法
仅想到的是在服务器关闭后运行清理。看起来像这样:
asc = Async()
try:
asyncio.run(run_server()) # You already do it now somewhere
finally:
asyncio.run(asc.close())
由于asyncio.run
每次都会创建新的事件循环,因此您可能想更深入地重用同一事件循环:
loop = asyncio.get_event_loop()
asc = Async()
try:
loop.run_until_complete(run_server())
finally:
loop.run_until_complete(asc.close())
只要知道自己在做什么,就可以多次拨打run_until_complete
。
带有代码段的完整示例:
import asyncio
class Async:
async def close(self):
print('closing')
return self
async def cleanup(self):
print('destructing')
await self.close()
loop = asyncio.get_event_loop()
asc = Async()
async def amain():
await asyncio.sleep(1) # Do something
if __name__ == '__main__':
try:
loop.run_until_complete(amain())
finally:
loop.run_until_complete(asc.cleanup())
loop.close()
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。