본문 바로가기
WEB/Django

Window 환경에서 django celery 오류 및 작동 방법

by Guardy 2023. 10. 24.
728x90

django 에서 비동기로 api를 처리하려면 celery를 사용하여야 한다.

다음 명령어로 celery를 설치한다.

pip install celery

그 다음 celery.py를 config 폴더 내에 다음과 같이 작성하여 준다.

from __future__ import absolute_import, unicode_literals
import os
from celery import Celery, shared_task
from django.conf import settings
from celery.schedules import crontab

# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.base')

app = Celery('config')

# Using a string here means the worker don't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
#   should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings', namespace='CELERY')

# Load task modules from all registered Django app configs.
app.autodiscover_tasks()

그 다음 app 폴더내에 tasks.py(반드시 이름을 tasks로 지정해야 함.) 를 다음과 같이 작성해준다.

from __future__ import absolute_import, unicode_literals
from celery import shared_task

from .models import Keyword

@shared_task
def test_task():
    kw = Keyword.objects.create(
        name="test",
    )
    kw.save()

그 다음 views.py에서 api를 정의해준다.

비동기로 처리할 것이기 때문에 delay를 이용하고, response로 200 status를 보낸다.

class Test(APIView):
    def get(self,request):
        test_task.delay()
        return Response(status=200)

이제 urls.py와 연결하여 api를 호출하였는데 무한 로딩 문제가 발생하였다.

무한 로딩 문제를 해결하기 위해서는 celery를 사용하기 위해서는 다음 명령어를 터미널을 새로 열고 입력하여야 한다.

celery -A config worker --loglevel=info

명령어를 친 뒤 api를 호출했는데 200 ok는 떴으나 db keyword에 test가 추가되지 않아서 무엇이 문제인지 로그를 살펴보았다.

[2023-10-24 13:51:56,243: ERROR/MainProcess] Task handler raised error: ValueError('not enough values to unpack (expected 3, got 0)')
billiard.einfo.RemoteTraceback:
"""
Traceback (most recent call last):
  File "C:\Users\guardy\anaconda3\lib\site-packages\billiard\pool.py", line 361, in workloop
    result = (True, prepare_result(fun(*args, **kwargs)))
  File "C:\Users\guardy\anaconda3\lib\site-packages\celery\app\trace.py", line 664, in fast_trace_task
    tasks, accept, hostname = _loc
ValueError: not enough values to unpack (expected 3, got 0)
"""

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\guardy\anaconda3\lib\site-packages\billiard\pool.py", line 361, in workloop
    result = (True, prepare_result(fun(*args, **kwargs)))
  File "C:\Users\guardy\anaconda3\lib\site-packages\celery\app\trace.py", line 664, in fast_trace_task
    tasks, accept, hostname = _loc
ValueError: not enough values to unpack (expected 3, got 0)

not enough value to unpack 오류를 해결하기 위해 gpt에 물어봐도 다음과 같은 대답만 내놓았다.

제공해주신 정보를 바탕으로, 코드는 정상적으로 구성된 것으로 보입니다. Celery 설정, 작업 정의, 그리고 뷰에서의 작업 호출 모두 예상대로 구성되어 있습니다. 그러나 "ValueError: not enough values to unpack (expected 3, got 0)" 오류는 여전히 Celery worker의 내부적인 문제로 보입니다.

다음은 몇 가지 추가적인 문제 해결 방법입니다:

  1. Celery와 관련된 패키지의 버전 확인/업데이트:
    • Celery와 관련된 패키지들(billiard, kombu 등)이 최신 버전인지 확인해보세요. 버전 충돌이나 특정 버전에서의 버그로 인해 이러한 문제가 발생할 수 있습니다.
      Copy code
      pip install -U celery billiard kombu
  2. Celery 실행 명령어 확인:
    • Celery worker를 실행하는 명령어가 정확한지 확인하세요. 프로젝트 디렉토리에서 다음 명령어를 사용해야 합니다:
    • cssCopy code
      celery -A config worker --loglevel=info
  3. Django 설정 파일 확인:
    • DJANGO_SETTINGS_MODULE이 올바르게 지정된 설정 파일을 가리키고 있는지 확인하세요. config.settings.base가 실제 설정 파일인지 확인하고, 필요에 따라 적절한 설정 파일로 수정하세요.
  4. Celery 앱 이름 확인:
    • Celery('config')에서 'config'는 Celery 앱의 이름입니다. 이것이 실제 Django 프로젝트의 이름과 일치하는지 확인하세요. 일반적으로 이것은 프로젝트 폴더의 이름과 같아야 합니다.
  5. 비동기 결과 백엔드 설정:
    • 결과 백엔드가 설정되어 있지 않은 경우, 작업의 상태를 추적할 수 없으며 이러한 오류가 발생할 수 있습니다. 결과 백엔드를 설정하려면, Celery 설정에 다음 코드를 추가하세요:
      pythonCopy code
      app.conf.update( result_backend='django-db', # 또는 'django-cache', 또는 다른 백엔드 )
  6. Celery 로깅:
    • 문제를 진단하기 위해 Celery의 로깅 레벨을 DEBUG로 설정할 수 있습니다. 이렇게 하면 추가 정보를 얻을 수 있어 문제 해결에 도움이 될 수 있습니다.
      cssCopy code
      celery -A config worker --loglevel=DEBUG
  7. 외부 패키지와의 충돌:
    • 때로는 다른 외부 패키지가 Celery와 충돌할 수 있습니다. 가상 환경을 새로 만들어서 프로젝트에 필요한 패키지만 설치해 보세요.

위의 방법들을 시도한 후에도 문제가 해결되지 않는다면, 해당 오류가 발생하는 더 많은 컨텍스트나 로그를 제공해주시면 더 구체적인 해결 방법을 제안드릴 수 있습니다.

위 해결법을 전부 해봤으나 해결되지 않아서 결국 구글링을 해서 나온 결론은 바로 eventlet을 이용하는 것이었다.

eventlet을 pip을 이용해 다음과 같이 설치해준다

pip install eventlet

그 다음 위에 있던 celery 명령어를 다음과 같이 입력해준다.

celery -A config worker -l info -P eventlet

이제 다시 api를 호출한 뒤에 admin page에서 확인해보면 정상적으로 test가 입력 된 것을 확인할 수 있다.

 

도움이 되셨다면 공감버튼과 댓글 부탁드립니다

728x90