【发布时间】:2019-10-30 21:25:06
【问题描述】:
我想将我自己的类的对象传递给 celery 任务。我没有使用 Django,这是我自己的自定义类,不可序列化。
经过研究,我想到了将对象内存id作为参数传递,然后根据this answer从id中获取对象:
tasks.py
import ctypes
@app.task
def my_task(obj_memory_id):
my_obj = ctypes.cast(obj_memory_id, ctypes.py_object).value
my_obj.my_method()
main.py
def main():
obj = MyClass()
obj_memory_id = id(obj)
my_task.delay(obj_memory_id)
现在,当我在 celery 之外执行它时,它可以工作。但是当我用芹菜做时,我得到:
billiard.exceptions.WorkerLostError: Worker exited prematurely: signal 11 (SIGSEGV).
为什么会这样?我该如何实现我的目标?
更多信息:我没有在 Celery 任务中实例化该类,因为该类实例化非常慢(1-2 秒)。就我的目的而言,即使是 1 秒的延迟也很多。我想提前准备好它的实例,当我需要调用它的方法时,立即执行。
【问题讨论】:
-
永远,永远在生产代码中这样做:
ctypes.cast(obj_memory_id, ctypes.py_object).value。 -
@juanpa.arrivillaga 为什么?
-
因为它依赖于实现细节(
id是 PyObject 标头的内存地址)和不安全的强制转换。无论如何,您的 celery 进程将无法从这样的单独进程中理解内存地址,请参阅:stackoverflow.com/questions/4352668/… -
@juanpa.arrivillaga 谢谢。那么你知道有什么方法可以将不可序列化的对象传递给 celery 任务吗?
-
不,它必须是可序列化的。
标签: python python-3.x redis celery pickle