假设我有:
- 一个由3对(登录名、密码)组成的列表,我打算为每对创建一个urlib2开启器
- Celery中的一项任务
- 并发=3
我想将每个开启器绑定到一个Task实例(因此每个任务都有自己的开启器,即使用不同的authcookie)。
我目前所做的是任务的子类:
class TaskWithOpener(Task):
abstract = True
_openers = None
@property
def openers(self):
if self._openers is None:
print 'creating openers for', self
(...)
print 'openers already created for ', self, ' just returning them'
return self._openers
并制作这样的任务:
@my_celery.task(rate_limit='5/m', base=TaskWithOpener)
def my_task():
opener = random.choice(my_task.openers)
但通过这种方式,每个任务都有多个打开器的列表,并且它们是为每个线程单独创建的,所以当有3个凭据对(登录名、密码)并且并发性=3时,我的程序会创建9个打开器,这是不可接受的。
这是Celery非常有效的行为。您基本上已经创建了一个类,该类为每个实例创建了三个opener并实例化了三次。
你要做的是生成三个任务,每个任务都有自己的一组凭据:
@celery.task(rate_limit='5/m')
def the_task(login, password):
opener = create_opener(login, password)
…
然后你可以这样称呼它:
credentials = [
('login1', 'password1'),
('login2', 'password2'),
('login3', 'password3'),
]
for login, password in credentials:
the_task.delay(login, password)
这样,工人将收到三项任务,并对其进行费率限制
更新:
从你的评论和代码中,我怀疑你想让选项成为一个类属性。
问题是重写self上的属性会使其成为实例属性。
我认为你试图创建一个类属性。
老实说,我认为这不是一个好的解决方案。我想知道你为什么不想每次都创造开场白。
这贵吗?然后,您要寻找的不是任务队列+工作程序,而是一些不断运行的服务器(可能是过度扭曲实现的)。