[Flask] ImportError: cannot import name '_app_ctx_stack'

Flask Dependency 문제 해결

문제

Kubernetes로 MSA 어플리케이션을 테스트하는 도중, 시작부터 난관에 부딪혔다.

K9S
K9S

Pods가 미친듯이 꺼졌다가 켜진다. 처음에는 쿠버네티스 세팅 문제인 줄 알았다. minikube부터 시작해서 k8s yaml 파일들에 문제가 없는 지 계속해서 체크했는데, 별 문제가 없어 보였다. 로그를 분석해보니 Flask 문제였다ㅠㅠ.

로그부터 분석하는 건 기본 중에 기본인데 멍충했다...

에러 내용은 다음과 같았다:

Traceback (most recent call last):
  File "/app/server.py", line 3, in <module>
    from flask_mysqldb import MySQL
  File "/usr/local/lib/python3.11/site-packages/flask_mysqldb/__init__.py", line 3, in <module>
    from flask import _app_ctx_stack, current_app
ImportError: cannot import name '_app_ctx_stack' from 'flask' (/usr/local/lib/python3.11/site-packages/flask/__init__.py)

대놓고서 Flask 에러이다. 근데 _app_ctx_stack을 flask 모듈에서 찾을 수 없다고 한다. 무슨 문제일까?

 

📌 _app_ctx_stack은 무엇일까? django는 Request를 인자로 전달받는 반면, flask는 전역적인 Request를 사용한다. 그로 인해 발생되는 동시성 제어를 관리하기 위해 context가 존재한다. _app_ctx_stack 어플리케이션 컨텍스트 스택으로, db configuration과 같은 정보를 담는다고 한다 [1].

해결

구글링을 해보니깐, Flask 2.2.0부터 무엇인가가 변경되면서, 외부 패키지 사용에 여러 충돌이 일어나고 있는 듯 하다 [2]. 그 중 하나가 바로 Python Version에 관한 문제였는데, 특히 나의 경우에 Python3.11 버전을 사용하면서, Flask와 버전 호환성이 맞지 않는 것으로 보인다.

requirements.txt:

blinker==1.6.2
click==8.1.7
Flask==3.0.0
Flask-MySQLdb==1.0.1
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.3
mysqlclient==2.2.0
PyJWT==2.8.0
PyMySQL==1.1.0
Werkzeug==3.0.0

dockerfile:

FROM python:3.11-slim-bullseye

RUN apt-get update \
    && apt-get install -y --no-install-recommends --no-install-suggests \
    build-essential default-libmysqlclient-dev pkg-config \
    && pip install --no-cache-dir --upgrade pip

WORKDIR /app
COPY ./requirements.txt /app/requirements.txt

RUN pip install --no-cache-dir -r /app/requirements.txt

COPY . /app

EXPOSE 5000

CMD ["python3", "server.py"]

위에를 보면, Flask는 3.0.0, Python은 3.11 버전을 사용하고 있다. 버전을 낮추자.

패키지 버전 낮추기

Image 생성 시에는 Dockerfile을 3.9로 바꾸어주자.

FROM python:3.9-slim-bullseye

# 나머지는 모두 동일

Flask 버전도 2.0.1로 낮추어준다.

Flask==2.0.2
// ...

그리고 image를 만들어서 올리면 된다.

만약에 로컬에서 Python 버전을 낮추려면, virtual environment만 바꾸어주면 된다.

$ brew install python@3.9
$ python3.9 -m venv venv
$ source venv/bin/activate
$ pip install --upgrade pip
$ pip install -r requirements.txt

결과

$ kubectl apply -f ./

Kubernetes Pod을 다시 실행하면...

K9S
K9S

문제 없이 작동한다.

Python 3.11 버전이 현재 나왔긴 한데, 엥간하면 아직까지는 3.9, 3.10 버전 등 좀 안정적인 버전을 사용하자. Flask나 django를 사용하는 데 있어서 어떤 이상한 에러가 나타날 지 모르기에...

참고 자료

  1. [Python] Flask 에서의 context 이해하기, jihwankim94, velog
  2. Cannot use module aioflask(Python) ..., stackoverflow