본문 바로가기
ОКБ (실험 설계국)/Trouble Shooting

12. [CentOS7, Python] Django Sqlite 버전 관련 에러 해결법

by Rosmary 2021. 6. 4.
728x90
반응형







1. 개요


Error Log:
...
File "/root/Django/Root/lib/python3.9/site-packages/django/db/backends/sqlite3/base.py", line 68, in check_sqlite_version
raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: SQLite 3.9.0 or later is required (found 3.7.17).
...

참고로 필자는 Python 3.9.3, Django 3.2.4를 사용하고 있다.



Python Django로 manage.py 파일을 이용해 db migrate를 진행 시, 위와 같은 에러가 나타나는 경우에 대한 해결 방법을 포스팅하려 한다. 위의 에러 로그는 Python 또는 pip로 설치된 Django의 버전에 따라 요구하는 sqlite의 버전이 다르게 표기될 수 있다.

Python으로 웹 서버를 만들기 위해 인터넷의 자료를 토대로 실습을 진행하려는 분들인 경우, 아마 위의 에러문구 때문에 실습 책을 제대로 넘기지도 못하고 정체되어 있을 가능성이 상당히 높다. 필자도 그 중 한 명이었는데, 몇 날 며칠의 삽질 끝에 이 에러를 해결할 수 있는 방법을 찾아 포스팅하게 되었다.


CentOS7을 사용하시는 분들이라면, 기본으로 설치된 python 버전은 2.7.5과 3.6.3 버전이다(3버전 Python은 python3라는 명령어를 사용하면 된다). 그리고 Django 실습 시 기본으로 사용하는 sqlite DB의 기본 버전은 3.7 버전이다. 문제는 기본으로 설치된 Python 3.6 버전에서 Django 사용 시, sqlite의 최소 요구 버전은 3.8 버전이라 별도의 업데이트가 필요한데, yum으로 패키지를 검색해보면 sqlite 기본 버전이 가장 최신 버전이라는 문구와 함께 업데이트가 불가능함을 발견할 수 있다.


python 실행 후, sqlite3 모듈을 import하여 버전을 확인하면 아래와 같이 Python 3버전에서 인식 가능한 SQLite 버전을 확인할 수 있다. 역시 Django가 요구하는 최소 버전을 만족하지 못함을 알 수 있다.

# 명령어: python3 -c "import sqlite3; print(sqlite3.sqlite_version)"




2. SQLite 최소 권장 버전 소스파일 설치

이 때문에 sqlite는 별도의 소스파일로 설치를 진행해야 한다. 아래의 명령어를 연달아 입력하여 sqlite의 최신 버전 설치를 진행하도록 하자.

---- < SQLite 3.35 버전 설치 > ------------------------------------------------------
# wget https://www.sqlite.org/snapshot/sqlite-snapshot-202106031851.tar.gz
# mv sqlite-snapshot-202106031851.tar.gz /usr/src
# cd /usr/src
# tar -xvf sqlite-snapshot-202106031851.tar.gz /usr/src
# cd sqlite-snapshot-202106031851
# ./configure 또는 ./configure --prefix="프로그램 파일 설치 경로"
# make
# make install
------------------------------------------------------------------------------------------
* configure의 옵션 등, 소스파일 설치와 관련된 내용은 여기를 참고하자.

설치된 sqlite의 명령어는 위와 같이 설치를 진행했다면, /usr/local/bin/ 폴더 내에 sqlite3 라는 이름으로 존재하게 된다.
이 명령어를 옵션 --version을 써서 실행시켜보면 우리가 설치하려하는 최신 버전과 동일함을 확인할 수 있다.

# 명령어: /usr/local/bin/sqlite3 --version



!! 참고
** 일반 명령어를 사용하듯이 sqlite3 --version을 입력하면 기본 설치 버전이 화면에 출력되는데, 기본 버전을 사용할 일이 없다면 아래의 명령어들을 입력하여 최신 버전의 sqlite3 명령어가 바로 사용될 수 있도록 하자.

# mv /usr/bin/sqlite3 /usr/bin/sqlite3_old -> 기존의 sqlite3 명령어 파일 이름을 sqlite3_old로 변경
# cp /usr/local/bin/sqlite3 /usr/bin/sqlite3 -> 최신 버전의 sqlite3 명령어를 /usr/bin으로 이동


혹자는 원래 존재하는 sqlite3 패키지를 삭제하는 것이 더 좋지 않을까 생각할 수도 있을 듯 한데, 기본 버전의 sqlite3 패키지에 의존성을 가지는 패키지들이 워낙 중요한 것이 많아서(systemd 등...) yum으로는 삭제가 불가능하다. rpm으로는 삭제가 가능하나, 삭제할 경우, yum은 물론이거나와 소스 파일을 사용하더라도 패키지 설치 자체가 불가능해진다. 주의하도록 하자.



이제 Python 3버전을 실행하여, 설치한 SQLite 버전이 Python에서 인식되는지 확인해보도록 하자.


분명 최신 버전의 SQLite를 설치했음에도 Python 3버전은 기존의 SQLite를 바라보고만 있다. 이는 Python이 SQLite DB와 연동하기 위해서 SQLite 폴더 내의 공유 라이브러리 파일을 인식해야하는데, Linux에서는 기본적으로 설치된 SQLite 버전의 공유 라이브러리 파일을 바라보도록 설정되어 있기 때문이다. 이를 우리가 소스파일로 설치한 최신 버전의 SQLite의 공유 라이브러리 파일을 바라볼 수 있도록 변경해주어야 한다.

대략 위와 같은 상황이라고 보면 된다.



3. 리눅스 공유 라이브러리 파일 경로 설정 변수 수정

Linux에는 LD_LIBRARY_PATH라는 이름의 환경 변수가 하나 존재한다. 이 변수의 역할을 조금 쉽게 설명하자면, 하나의 프로그램(A라고 가정하자)이 다른 프로그램(B라고 가정하자)과 연동하여 사용될 때, B프로그램의 내용이 A에 쉽게 인식될 수 있는 B 프로그램의 특정 파일(라이브러리 파일) 경로를 지정하는 것이라 보면 된다.

이 변수값은 echo 명령어를 사용하여 확인할 수 있는데, 별도의 설정이 없는 상태라면 빈 값으로 표시된다.
# echo $LD_LIBRARY_PATH


env 명령어를 입력하면 Linux의 모든 환경변수를 확인할 수 있는데, 여기에 LD_LIBRARY_PATH는 나타나지 않는 것을 확인할 수 있다.


환경변수 등록을 위해서 export 명령어를 사용하는데, export 명령어는 쉘에서 설정한 쉘 변수를 환경 변수로 등록해주는 역할을 한다. 아래의 명령어를 사용하여 LD_LIBRARY_PATH값을 최신 SQLite3 버전의 라이브러리 파일이 있는 경로로 지정한 뒤 환경 변수에 등록해주도록 하자.

# export LD_LIBRARY_PATH="/usr/local/bin"
(잘못된 환경 변수를 등록했다면 unset LD_LIBRARY_PATH 명령어를 사용하여 등록된 환경 변수를 삭제하면 된다)


환경변수가 등록되어 있다면 python3에서 인식하는 sqlite3의 버전이 달라진 것을 확인할 수 있다.


이제, 다시 SQLite DB에 대해 migration을 진행해보자. 아래와 같이 에러없이 정상적인 진행과정이 나타난다면 성공이다.



하지만, 위와 같이 export 명령어만으로 LD_LIBRARY_PATH 환경변수를 등록하면, Terminal이 종료되는 순간, 환경변수가 사라진다. 이 환경변수를 영구적으로 등록하고 싶다면, /etc/profile 파일에 위의 export 명령어를 등록해주면 된다.





!! 참고
Python 3.9 버전에서는 위와 같은 조치에도 불구하고 또 다른 에러가 발생하는 것을 확인할 수 있다.

Error:
...
File "/root/Django/Root/lib/python3.9/site-packages/django/utils/asyncio.py", line 26, in inner
return func(*args, **kwargs)
File "/root/Django/Root/lib/python3.9/site-packages/django/db/backends/sqlite3/base.py", line 217, in get_new_connection
create_deterministic_function('django_date_extract', 2, _sqlite_datetime_extract)
django.db.utils.NotSupportedError: deterministic=True requires SQLite 3.8.3 or higher
...


이 에러는 sqlite3에 존재하는 base.py 파일 안의 create_deterministic_function의 내부 변수값과 관련이 있다.
해당 함수의 변수 중 deterministic이라는 이름의 Bool 변수가 있는데, 이 변수값이 True인 경우, 위와 같은 에러가 나타남을 확인했다.

deterministic 값을 False로 변경하고 저장한 뒤 다시 진행하면 정상적으로 migrate이 진행됨을 알 수 있다.






Fin.

반응형

댓글