• 카테고리

    질문 & 답변
  • 세부 분야

    풀스택

  • 해결 여부

    해결됨

celery을 이용해서 비동기처리를 수행하는데 질문입니다!

23.03.29 18:54 작성 23.03.29 19:17 수정 조회수 324

0

안녕하세요 진석님! 현재 강의를 들은 다음 웹페이지를 만들고 있는데 사진과 함께 포스팅을 하면 사진에 있는 글자를 인식하여 번역하고 따로 필드에 저장하는 것을 구현하고 있습니다.(google cloud visionAI, translationAPI 이용)

현재 celery을 사용하는 방법은 따로 찾아봐서 잘 알게되엇는데(https://realpython.com/asynchronous-tasks-with-django-and-celery/)

#views.py
from .tasks import process_image_ocr_and_translation
     
class PostViewSet(ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    permission_classes = [AllowAny]

    def perform_create(self, serializer):
        post = serializer.save(author=self.request.user)  
        tag_list = post.extract_tag_list()
        post.tag_set.add(*tag_list)
        process_image_ocr_and_translation.delay(post.id)

# tasks.py
from celery import shared_task
from .models import Post
from module.API import detect_text, translate_text


@shared_task
def process_image_ocr_and_translation(post_id):
    post = Post.objects.get(pk=post_id)
    post.photo.file.open()
    image_path = post.photo.path
    detected_text = detect_text(image_path)
    translated_text = translate_text(detected_text)
    post.ocr_text = translated_text
    post.save()

#celery.py

import os

from celery import Celery

# Set the default Django settings module for the 'celery' program.
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "backend.settings.dev")

app = Celery("backend")

# Using a string here means the worker doesn'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 apps.
app.autodiscover_tasks()


@app.task(bind=True)
def debug_task(self):
    print(f"Request: {self.request!r}")
#common.py

# Celery settings
# 베포를 할때는 이부분이 변경이 되어야 한다?
CELERY_BROKER_URL = "redis://localhost:6379"
#: Only add pickle to this list if your broker is secured
#: from unwanted access (see userguide/security.html)
# CELERY_ACCEPT_CONTENT = ["application/json"]
CELERY_RESULT_BACKEND = "redis://localhost:6379"
# CELERY_TASK_SERIALIZER = "json"
#module.API
from google.cloud import vision
import io
from google.cloud import translate


def detect_text(path):
    """Detects text in the file."""

    client = vision.ImageAnnotatorClient()

    with io.open(path, "rb") as image_file:
        content = image_file.read()

    image = vision.Image(content=content)

    response = client.text_detection(image=image)
    if response.error.message:
        raise Exception(
            "{}\nFor more info on error messages, check: "
            "https://cloud.google.com/apis/design/errors".format(response.error.message)
        )
    texts = response.text_annotations
    return texts[0].description


# Initialize Translation client
def translate_text(text, project_id="myproject-capston"):
    """Translating Text."""

    client = translate.TranslationServiceClient()

    location = "global"

    parent = f"projects/{project_id}/locations/{location}"

    # Translate text from English to French
    # Detail on supported types can be found here:
    # https://cloud.google.com/translate/docs/supported-formats
    response = client.translate_text(
        request={
            "parent": parent,
            "contents": [text],
            "mime_type": "text/plain",  # mime types: text/plain, text/html
            "source_language_code": "en-US",
            "target_language_code": "ko",
        }
    )

    # Display the translation for each input text provided
    for translation in response.translations:
        print("Translated text: {}".format(translation.translated_text))

번역된 결과물 자체는 잘 나오는거 같으나(python -m celery -A backend worker실행화면에서 translate_text()함수에 결과값을 print하도록 설정했더니 "Translated text: ~~~~ " 이렇게 콘솔에 잘 나타납니다) post.ocr_text필드상에 null값이 입력이 됩니다...

post.ocr_text필드속성에 null=True, blank=True 로 되어있고 비동기처리하기전에도 계속 null값이 들어가서(visionai와 translation이 시간이 좀 걸리다보니?) 비동기로 처리할려고 했는데도 여전히 null값이 들어가네요ㅜㅜ 어떻게 해결해야 할까요?? post.save()위치를 tasks.py안이나 views.py에서 비동기 작업은 조건문을 거는 방식 등등을 해보았으나 때에 따라서는 "ocr_text": "5f69b757-0f24-4cc4-947c-f8c624b48dde", 이런식으로 결과가 나오기도 하네요... 똑같은 사진인데도 매번 다른 16진수가 들어가던걸 확인했는데 번역된 결과값은 아닌거 같습니다...

아 추가적으로 코드를 바꿀때마다 celery worker은 매번 재시작하였습니다

답변 1

답변을 작성해보세요.

0

꺼넝님의 프로필

꺼넝

질문자

2023.03.29

아... 해결했습니다... 제가 잘못했네요 디버깅하다보니 발견했는데 translate_text()함수에 return을 안했네요! 하하

맞습니다. :-)

파이썬 함수에서 아무 것도 반환하지 않으면, None을 리턴한 것으로 처리합니다.

잘 해결하셨습니다. 👍