访问私有 _value 属性不是正确的方法,至少有两个原因:一个是该属性是私有的,可以在未来版本中删除、重命名或更改含义,恕不另行通知,另一个是增加已经有服务员的信号量不会注意到 limit。
由于asyncio.Semaphore 不支持动态修改限制,您有两种选择:实现自己的支持它的Semaphore 类,或者根本不使用Semaphore。后者可能更容易,因为您总是可以用固定数量的工作任务替换信号量强制限制,这些工作任务通过队列接收作业。假设您当前的代码如下所示:
async def fetch(limit, arg):
async with limit:
# your actual code here
return result
async def tweak_limit(limit):
# here you'd like to be able to increase the limit
async def main():
limit = asyncio.Semaphore(10)
asyncio.create_task(tweak_limit(limit))
results = await asyncio.gather(*[fetch(limit, x) for x in range(1000)])
您可以通过提前创建工作人员并让他们有工作去做来表达它而无需信号量:
async def fetch_task(queue, results):
while True:
arg = await queue.get()
# your actual code here
results.append(result)
queue.task_done()
async def main():
# fill the queue with jobs for the workers
queue = asyncio.Queue()
for x in range(1000):
await queue.put(x)
# create the initial pool of workers
results = []
workers = [asyncio.create_task(fetch_task(queue, results))
for _ in range(10)]
asyncio.create_task(tweak_limit(workers, queue, results))
# wait for workers to process the entire queue
await queue.join()
# finally, cancel the now-idle worker tasks
for w in workers:
w.cancel()
# results are now available
tweak_limit() 函数现在可以通过生成新工作人员来增加限制:
async def tweak_limit(workers, queue, results):
while True:
await asyncio.sleep(1)
if need_more_workers:
workers.append(asyncio.create_task(fetch_task(queue, results)))