Python对象的资源管理

ya.resourcepool的Python项目详细描述


https://github.com/knowikow/ya.resourcepool.py/workflows/tests/badge.svg

又是一个资源库

可配置的资源池。ResourcePool类可以使用可配置函数分配资源, 存储它们以备以后使用,如果池太大,也可以释放它们。在

所有代码示例假定:

>>> from ya.resourcepool import *
>>> import threading
>>>
>>> class R(int):
...     lock = threading.Lock()
...     current = 0  # last generated number
...     deallocated = []
...
...     def __new__(cls, *args, **kwds):
...         with R.lock:
...             R.current += 1
...             instance = super().__new__(cls, R.current)
...         return instance
...
...     def __init__(self):
...         self.alive = True
...
...     def close(self):
...         self.alive = False
...         R.deallocated.append(self)
...         return self
...
...     def use(self):
...         print(f'Using resource {self}')
...         return self

使用示例

最基本的例子只配置了资源和用途的分配方法 ResourcePool.__call__()从池中获取资源:

^{pr2}$

这假设资源可以简单地被垃圾回收,并且 可以分配金额。在

注意,ResourcePool.__call__()应该用作上下文管理器。如果不需要的话, 可以使用ResourcePool.pop()ResourcePool.push()方法:

>>> pool = ResourcePool(alloc=R)
>>> obj = pool.pop()
>>> obj.use()
Using resource ...
>>> pool.push(obj)

注意,ResourcePool.pop()将资源的所有权转移到客户机代码,它是客户机的 负责清理资源或使用ResourcePool.push()将其返回池。在

ResourcePool.push()方法也可用于向池中添加新资源:

>>> pool = ResourcePool()  # no alloc argument
>>> obj = R()              # create/allocate a resource
>>> pool.push(obj)         # push without preceding pop

ResourcePool.__call__()方法实际上是根据poppush来实现的。在

有限的资源集

如果可用的资源实例数量有限,则可以使用init参数提供一个集合:

>>> resources = [R()]
>>> pool = ResourcePool(init=resources)
>>> with pool() as obj:
...     obj.use()
Using resource ...

在这种情况下,不会分配新的资源,只会使用初始值设定项中给定的资源。在

默认情况下,尝试从受限池获取资源将引发^{tt13}类型的异常$ 如果目前没有可用的免费资源:

>>> pool = ResourcePool(init=[])  # note the empty list
>>> with pool() as obj:
...     obj.use()
Traceback (most recent call last):
   ...
ya.resourcepool.ResourcePoolEmpty

或者,可以给出以秒为单位的超时:

>>> pool = ResourcePool()  # an empty list is actually the default for init
>>> with pool(timeout=5) as obj:
...     obj.use()
Traceback (most recent call last):
   ...
ya.resourcepool.ResourcePoolEmpty

这只会在给定的5秒超时之后引发异常。请注意,超时是 浮点数,所以秒的分数是可能的。零或更少的超时将永远阻塞 或者直到有资源可用。在

init参数可以与alloc参数组合使用:

>>> resources = [R()]
>>> pool = ResourcePool(init=resources, alloc=R)
>>> with pool() as obj:
...     obj.use()
Using resource ...

这将使用初始资源列表,并且只有在初始资源耗尽时才分配新的资源列表。在

资源释放

资源通常需要在某个时候被释放。执行此操作的函数可以是 使用dealloc初始值设定项参数给定:

>>> pool = ResourcePool(alloc=R, dealloc=R.close)
>>> with pool() as obj:
...     obj.use()
Using resource ...

当池对当前由池管理的所有资源进行垃圾回收时,这将调用R.close()。在

资源保留策略

{18$resources}可以通过初始化器^来定位{18资源:

>>> pool = ResourcePool(alloc=R, maxsize=100)

当给定一个maxsize参数,并且在返回 资源到池中,所有剩余的将被释放。此进程还将使用可选的dealloc 参数,或者只将其从池中移除并进行垃圾回收。在

还有一个额外的参数minsize,用于控制将要释放的资源量 在溢出情况下:

>>> pool = ResourcePool(alloc=R, maxsize=100, minsize=50)

这将通过在池大小超过100时释放剩余资源将池大小减小到50 push操作。在

另一个参数maxage可用于设置资源在 游泳池。minsize参数可用于保证最少的池资源集, 不管年龄。在

资源活动检查

在从pop返回资源池之前,可以检查它们的状态。这个 可以使用check参数配置:

>>> pool = ResourcePool(alloc=R, check=lambda resource: resource.alive)
>>> with pool() as obj:
...     obj.use()
Using resource ...

check中给定的对象必须是一个可调用的对象,它接受资源实例并返回一个truthy 价值观。在返回之前,将为结果值候选者pop调用它,如果 结果可转换为False,则资源被视为已死亡并将被丢弃 不调用任何dealloc过程。pop将继续尝试获取有效资源。在

朝自己的脚开枪

通过使用空的固定大小池并使用超时值0,可以无限期地阻塞线程:

>>> pool = ResourcePool()
>>>
>>> def allocate(pool):
...     pool.push(R())
>>>
>>> threading.Timer(5, allocate, (pool,)).start()
>>>
>>> with pool(timeout=0) as obj:
...     obj.use()
Using resource ...

如果没有Timer线程在5秒后将新对象添加到池中,则此代码将永远阻塞。在

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java Clojure关键字在内存中的大小是多少?   Java中有固定长度的通用数组对象吗?   PostgreSQL:通过Java更新我的用户表   错误:使用java解析xml   java Json显示列表中对象的名称   java比较JodaTime时区   与JAVA中的API和包的区别?   java的int值在for循环中不改变   谷歌应用引擎中的java RSA   迁移到spring 5后出现java非法字符错误   java Websphere管理控制台不工作   JavaGSON如何始终在json中包含毫秒?   带有空格和双引号的windows Java ProcessBuilder命令参数失败   java错误:重复的zip条目[43.jar:org/apache/http/annotation/NotThreadSafe.class]