Python 芹菜:运行冗长初始化功能的正确方法(每个进程)

Python 芹菜:运行冗长初始化功能的正确方法(每个进程),python,initialization,multiprocessing,celery,python-c-extension,Python,Initialization,Multiprocessing,Celery,Python C Extension,TLDR 要为芹菜产生的每个进程运行初始化函数,可以使用worker\u process\u init信号。正如您在中所读到的,该信号的处理程序阻塞时间不应超过4秒。 但是,如果我必须运行一个需要4秒以上执行的init函数,那么有哪些选项呢 问题 我使用C扩展模块在芹菜任务中运行某些操作。该模块需要几秒钟(可能4-10秒)的初始化。由于我不希望为每个任务运行此init函数,而是为生成的每个进程运行此init函数,因此我使用了worker\u process\u init信号: #lib.py

TLDR

要为芹菜产生的每个进程运行初始化函数,可以使用
worker\u process\u init
信号。正如您在中所读到的,该信号的处理程序阻塞时间不应超过4秒。 但是,如果我必须运行一个需要4秒以上执行的init函数,那么有哪些选项呢

问题

我使用C扩展模块在芹菜任务中运行某些操作。该模块需要几秒钟(可能4-10秒)的初始化。由于我不希望为每个任务运行此init函数,而是为生成的每个进程运行此init函数,因此我使用了
worker\u process\u init
信号:

#lib.py 
import isclient #c extension module
client = None
def init():
    global client
    client = isclient.Client() #this might take a while

def create_ne_list(text):
    return client.ne_receiventities4datachunk(text)

#celery.py
from celery import Celery
from celery.signals import worker_process_init
from lib import init

celery = Celery(include=[
    'isc.ne.tasks'
])

celery.config_from_object('celeryconfig')

@worker_process_init.connect
def process_init(sender=None, conf=None, **kwargs):
    init()

if __name__ == '__main__':
    celery.start()

#tasks.py
from celery import celery
from lib import create_ne_list as cnl

@celery.task(time_limit=1200)
def create_ne_list(text):
    return cnl(text)
当我运行这段代码时,我在前面的问题()中描述了会发生什么。简言之:由于我的init函数需要4秒以上的时间,有时会发生一个工作进程被杀死并重新启动,在重新启动过程中会再次被杀死,因为这是在4秒无响应后自动发生的。这最终会导致无限重复的终止和重启过程

另一个选项是使用信号
worker\u init
为每个worker只运行一次my init函数。如果我这样做,我会遇到另一个问题:现在排队的进程由于某种原因被卡住了。 当我以3的并发性启动worker,然后发送两个任务时,前三个任务将完成,其余的任务将不被触及。(我认为这可能与以下事实有关:
客户机
对象需要在多个进程之间共享,并且由于某些原因,C扩展不支持这一点。但老实说,我对muli处理相对较新,所以我只能猜测)

问题


因此,问题仍然存在:如何在每个进程上运行init函数,而该进程的运行时间超过4秒?有没有正确的方法可以做到这一点?那是什么方法?

芹菜将初始化超时处理限制为4.0秒。 检查

为了解决这个限制,你可以考虑在创建芹菜APP/P>之前改变它。

from celery.concurrency import asynpool
asynpool.PROC_ALIVE_TIMEOUT = 10.0 #set this long enough

请注意,没有配置或设置来更改此值。

这怎么不是重复的?@Veedrac它根本不是?它应该如何复制?这更像是一个后续问题。我想在以后的阅读中我会明白其中的区别。问题是这两篇文章都没有明确的问题陈述,所以不清楚需要什么答案。@Veedrac说得好。我编辑了这个问题,希望它现在能更清楚地回答我的问题。我很确定子类任务类会在每个进程中运行一次init函数。您应该能够将long init函数放在其中。您必须进行一些重构,并将
base=YourTaskSubclass
添加到任务装饰器中。