排队的任务数;如何避免全局变量?

时间:2018-07-23 15:33:58

标签: python python-asyncio

我正在编写基于asyncio的极简代码,它由任务,工作程序和队列组成:

  • 工人在队列中查找任务并执行
  • 任务表示为随机asyncio.sleep()
  • 任务完成后,会将另外两个任务添加到队列中

两个限制:

  • 一次最多10人
  • 总共应执行100个任务,脚本应在那时结束

要监视执行的任务总数,我使用一个全局变量task_queued,每次将任务添加到队列时都会更新。

我敢肯定,有一种更好的pythonic方式可以做到这一点,而不使用全局变量,但是我想出的所有解决方案都更加复杂。

我在这里缺少任何线索吗?

这是我的代码:

Eureka

1 个答案:

答案 0 :(得分:1)

感谢user4815162342的回答,如果有人感兴趣,请参见以下代码

import asyncio
from random import random
import sys


class Factory:
    """
    Factory
    """

    def __init__(self, max_workers, max_tasks):
        self.task_queued = 0
        self.max_workers = max_workers
        self.max_tasks = max_tasks

        self.queue = asyncio.Queue()

    async def task(self, task_id):
        sleep_time = 0.5 + random()
        print('     Begin task #{}'.format(task_id))
        await asyncio.sleep(sleep_time)

        if self.task_queued < self.max_tasks:
            await self.queue.put(task_id + ".1")
            self.task_queued += 1
        if self.task_queued < self.max_tasks:
            await self.queue.put(task_id + ".2")
            self.task_queued += 1

        print('     End task #{} ({} item(s) in the queue)'.format(task_id, self.queue.qsize()))


    async def worker(self, worker_id):
        while True:
            task_id = await self.queue.get()
            print('Worker #{} takes charge of task {}'.format(worker_id, task_id))
            await self.task(task_id)
            self.queue.task_done()


    async def organize_work(self):
        print('Begin work \n')

        await self.queue.put("1") # We add one task to the queue to start
        self.task_queued += 1

        workers = [asyncio.create_task((self.worker(worker_id + 1))) for worker_id in range(self.max_workers)]

        await self.queue.join()

        print('Queue is empty, {} tasks completed'.format(self.task_queued))
        for w in workers:
            w.cancel()
        print('\nEnd work')


if __name__ == '__main__':
    loop = asyncio.get_event_loop()

    factory = Factory(max_workers=3, max_tasks=50)

    try:
        loop.run_until_complete(factory.organize_work())

    except KeyboardInterrupt:
        print('\nBye bye')
        sys.exit(0)