Python对象的资源管理
ya.resourcepool的Python项目详细描述
又是一个资源库
可配置的资源池。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__()方法实际上是根据pop和push来实现的。在
有限的资源集
如果可用的资源实例数量有限,则可以使用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秒后将新对象添加到池中,则此代码将永远阻塞。在
- 项目
标签: