提前感谢:)
我有这个异步Celery任务调用:
update_solr.delay(id, context)
其中id是一个整数,context是Python dict。
我的任务定义如下:
@task
def update_solr(id, context):
clip = Clip.objects.get(pk=id)
clip_serializer = SOLRClipSerializer(clip, context=context)
response = requests.post(url, data=clip_serializer.data)
其中clip_serializer.data
是dict,url
是表示网址的字符串。
当我尝试拨打update_solr.delay()
时,我收到此错误:
PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemethod failed
任务的参数都不是实例方法,所以我很困惑。
当任务代码同步运行时,没有错误。
更新:修正了有关传递pk而不是对象的评论。
答案 0 :(得分:4)
context
dict中有一个对象,我不知道......
为了解决这个问题,我在异步调用之前执行了依赖于context
的代码,并且只传递了一个只包含本机类型的dict:
def post_save(self, obj, created=False):
context = self.get_serializer_context()
clip_serializer = SolrClipSerializer(obj, context=context)
update_solr.delay(clip_serializer.data)
任务结束如下:
@task
def update_solr(data):
response = requests.post(url, data=data)
这非常合适,因为将此作为异步任务的唯一目的是使POST无阻塞。
感谢您的帮助!
答案 1 :(得分:1)
尝试传递模型实例主键(pk
)。这对于泡菜来说要简单得多,减少了有效载荷并避免了竞争条件。
答案 2 :(得分:0)
import pickle
class X:
def y(self):
pass
pickle.dumps(X.y)
Pickle以递归方式工作,因此它可能位于对象图中的任何位置。您获得了解决方案 - 仅传输最小对象,即主键等,而不是Django模型对象。