芹菜工

时间:2016-11-26 17:35:15

标签: python celery

我有一个正在运行的芹菜服务器,使用redis作为borker和结果存储(python3)。我想有一个任意函数,它没有被注册到服务器,由芹菜工人执行。我尝试使用包marshal(在Is there an easy way to pickle a python function (or otherwise serialize its code)?之后)序列化此函数,并将字节码传输给worker:

celery_server.py:

from celery import Celery
import types
import marshal

app = Celery('tasks', broker='redis://guest@localhost//', backend='redis://localhost')

@app.task
def run_fct( fct_code, args, kwargs ):
    code = marshal.loads( fct.__code__ )
    func = types.FunctionType(code, globals(), "some_func_name" )

    return fct( *args, **kwargs )

client.py

from celery_server import run_fct
import marshal

def calc( x, y ):
    return x*y

fct_code = marshal.dumps( calc.func_code )
run_fct.apply_async( (fct_code, 10, 2 ) )

我在客户端遇到以下错误:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe3 in position 0: invalid continuation byte

bytes_to_str的{​​{1}}函数中。

是否有另一种或更好的方法来执行我的功能?

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

我找到了一个解决方案:通过包装我的函数并将包装函数作为参数提供给芹菜任务来解决UnicodeDecodeError

celery_server.py:

class MyFunction( object ):
    def __init__(self, fct):
        self.fct_code = marshal.dumps( fct.__code__ )

    def run(self, *args, **kwargs):
        run_fct.apply_async( args=(self,)+args, kwargs=kwargs, serializer='pickle' )

并在client.py中:

from celery_server import MyFunction

myFct = MyFunction( calc )
myFct.run( x=10, y=2 )

然后它就像一个魅力。

然而,使用包cloud解决了我的函数在工作者端的依赖性问题,例如,如果我在我的函数中使用了其他函数或包:

from celery import Celery
import cloud
import pickle

app = Celery('tasks', broker='redis://guest@localhost//', backend='redis://localhost')

class MyFunction( object ):
    def __init__(self, fct):
        self.serialized_code = cloud.serialization.cloudpickle.dumps(fct)

    def run(self, *args, **kwargs):
        run_fct.apply_async( args=(self,)+args, kwargs=kwargs, serializer='pickle' )

@app.task
def run_fct( myFct, *args, **kwargs ):
    fct = pickle.loads( myFct.serialized_code )

    return fct( *args, **kwargs )

client.py:

from tasks import MyFunction
import time

def calc( x, y ):
    time.sleep(5)
    return x*y

myFct = MyFunction( calc )
myFct.run( x=10, y=2 )

但是:当前cloud不支持python3。