You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Celery绑定类方法为任务触发AttributeError属性缺失问题求解

错误根因分析
  • 你将Celery任务定义为类的实例方法属于错误用法:@shared_task(bind=True) 绑定的是Celery任务自身的实例,当你用该装饰器装饰类方法时,方法第一个参数接收到的是Celery任务对象,不是你自定义的myClass类的实例,这直接导致两个报错:
    1. 你在方法里访问self.location的时候,这里的self是Celery的download_all任务对象,自然没有location属性
    2. celery-progress的progress_recorder需要绑定Celery任务实例来调用update_state,但你把myClass的实例传进去了,自然没有该方法
  • myClass的__init__方法里直接调用download_all逻辑错误,你要做异步任务的话不应该在实例初始化时同步执行该方法
  • views层的调用逻辑完全混乱:你既在实例化myClass的时候直接调用了download_all,又尝试对实例调用delay,还重复调用download_all取task_id,完全不符合Celery的调用规范
修复方案

1. 调整functions.py逻辑

将download_all从myClass中剥离为独立的Celery任务,避免实例指向混乱:

import os
import shutil
from celery import shared_task
from celery_progress.backend import ProgressRecorder

class myClass():
    def __init__(self, n_user, n_password, n_url, n_port, db_password, username):
        self.location = zt_dosya_url # 确保该变量可正常获取,建议存到Django settings中统一调用
        self.static_fields = {}
        self.username = username
        self.n_user = n_user
        self.n_password = n_password
        self.n_url = n_url
        self.n_port = n_port
        self.db_password = db_password

    def send(self):
        # 保留你原有的send逻辑
        pass

# 独立定义Celery异步任务
@shared_task(bind=True)
def download_all_task(self, location, n_user, n_password, n_url, n_port, db_password, username):
    progress_recorder = ProgressRecorder(self)
    
    if not os.path.exists(location):
        os.mkdir(location)
    else:
        shutil.rmtree(location, ignore_errors=True)
        os.mkdir(location)

    # 保留你原有获取scans的业务逻辑
    scans = []
    len_scans = len(scans)
    for i, s in enumerate(scans):
        scanner.scan_name = s['name']
        # 你的原有业务逻辑
        progress_recorder.set_progress(i + 1, len_scans, f'On iteration {i}')
    
    # 下载完成后执行send逻辑
    my_class_instance = myClass(n_user, n_password, n_url, n_port, db_password, username)
    my_class_instance.send()

2. 修正views.py调用逻辑

直接调用异步任务获取task_id,不要多余的myClass实例化操作:

def setup_wizard(request):
    # 保留你原有获取setup对象的逻辑
    task = download_all_task.delay(
        zt_dosya_url, # 传入location参数
        setup.n_username, 
        setup.n_password,
        setup.n_url, 
        setup.ns_port, 
        setup.db_password,
        request.user.username
    )
    task_id = task.task_id
    context = {
        'task_id': task_id
    }
    # 保留你原有返回逻辑

内容的提问来源于stack exchange,提问作者edche

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 05:36:05