준호씨의 블로그

정원사들 시즌5 python3.6 -> python3.7 업그레이드 본문

개발이야기/호스팅관리

정원사들 시즌5 python3.6 -> python3.7 업그레이드

준호씨 2020. 4. 12. 23:37
반응형

정원사들 출석부

 

정원사들 시즌5가 시작되었고 저는 또 시즌5의 출석부를 담당하고 있습니다.

 

정원사들 시즌5 시작. 일일커밋

이틀 전 (2020.03.02)부터 정원사들 시즌5가 시작되었습니다. 정원사들이라는 모임은 그날그날 공부하고 알게 된 것을 github 에다가 커밋을 하는 사람들의 모임입니다. 시즌2부터 참여해서 벌써 시즌5가 되었네요..

junho85.pe.kr

지난 시즌에서도 이슈가 있었지만 출석이 누락되는 경우가 있어서 수작업으로 출석을 등록해 주는 작업을 했었는데요. 이번 시즌에서도 해당 이슈가 발생했습니다. 결국 야크 쉐이빙스러운 작업이긴 했지만 정원사들 시즌5 출석부를 python3.6 사용하던걸 python3.7로 변경하였습니다. 뜬금없이 웬 python 버전업?

 

상황 요약

상황을 요약해 보면 이렇습니다.

정원사 참가자의 slack 메시지 누락으로 출석이 누락되어서 수동 추가 요청이 들어왔습니다.

mongodb 에 직접 넣어 주면 되지만 github commit 내역을 눈으로 보고 timestamp 정보를 뽑아내어서 등록해주어야 합니다.

스마트하지 못한 거 같아서 github api로 commit 내역을 불러와서, commit 날짜를 파싱 해서 스크립트로 넣어 줄 수 있는 코드를 작성하였습니다.

그런데 스크립트로 작성한 제 컴퓨터는 python 3.7을 사용하고 있었고, 서버는 python 3.6을 사용하고 있었습니다. 제 컴퓨터에서는 스크립트가 잘 동작했는데 서버에서 돌려 보니 오류가 발생했습니다.

그래서 결국 python 3.7로 업그레이드를 하게 되었습니다.

django를 사용하고 있지만 apache와의 연동을 위해서 mod_wsgi를 사용하고 있는데요. 이것도 python 버전에 영향을 받다 보니 업그레이드해 주었습니다.

 

결국 데이터를 잘 가공해서 db에 직접 넣어주면 되었을 작업이긴 한데요. 혹시나 출석 누락이 더 생긴다면 종종 직접 작업을 해 주어야 하기 때문에 기능으로 만들어 두면 좋겠죠. 한 번에 다 할 수는 없으니 스크립트 작업을 먼저 했습니다. 언젠가 기능으로 들어갈 날도 올 수 있겠죠?

 

작업과 관련된 내용들을 좀 더 정리해 보았습니다.

 

github API로 커밋 정보 불러오기

github commit은 commit마다 고유의 url을 가지게 됩니다. 예를 들면 https://github.com/junho85/garden5/commit/7fc90ca7f2c923d90321523314ff877312113f64입니다. 이 커밋의 정보를 github API를 이용해서 메타 정보를 불러올 수 있습니다.

url을 조금 바꿔서 (github.com/ -> api.github.com/repos, commit -> commits) 다음처럼 호출해 주면

https://api.github.com/repos/junho85/garden5/commits/7fc90ca7f2c923d90321523314ff877312113f64

json으로 된 commit 정보를 보여줍니다.

저는 커밋 날짜 정보가 필요했기에 commit.author.date 정보를 이용했습니다. YYYY-MM-DDTHH:MM:SSZ 형식을 사용하고 있습니다.

python 3.7과 python 3.6의 strptime 동작 차이

서버는 python 3.6을 사용하고 있는데, 제 개발환경이 python 3.7을 사용하고 있었습니다. python 3.7에서는 YYYY-MM-DDTHH:MM:SSZ 형식의 날짜 시간 정보를 잘 파싱 합니다.

$ python             
Python 3.7.6 (default, Dec 30 2019, 19:38:26) 
[Clang 11.0.0 (clang-1100.0.33.16)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from datetime import datetime
>>> datetime.strptime("2020-04-12T23:04:51Z", "%Y-%m-%dT%H:%M:%S%z")
datetime.datetime(2020, 4, 12, 23, 4, 51, tzinfo=datetime.timezone.utc)

하지만 python 3.6에서는 제대로 파싱 하지 못했습니다.

$ python3
Python 3.6.8 (default, Oct  7 2019, 12:59:55)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from datetime import datetime
>>> datetime.strptime("2020-04-12T23:04:51Z", "%Y-%m-%dT%H:%M:%S%z")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.6/_strptime.py", line 565, in _strptime_datetime
    tt, fraction = _strptime(data_string, format)
  File "/usr/lib/python3.6/_strptime.py", line 362, in _strptime
    (data_string, format))
ValueError: time data '2020-04-12T23:04:51Z' does not match format '%Y-%m-%dT%H:%M:%S%z'

그래서 결국 서버의 python을 python 3.7로 올리기로 합니다.

ubuntu 서버에 python 3.7 설치하기

처음에는 apt으로 설치가 안될 거라 생각하고 python 3.7을 소스코드 빌드 방식으로 설치하려고 했었는데요. openssl 문제로 삽질을 하던 중에 apt로 설치가 된다는 것을 알게 되었습니다.

sudo apt install python3.7

로 설치하면 됩니다. ubuntu 버전마다 좀 다를 수 있겠는데요. 제가 사용하는 서버의 ubuntu 버전은 18.04.1입니다.

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.1 LTS
Release:        18.04
Codename:       bionic

현재 서버에는 3가지 버전의 python이 설치된 상태입니다.

$ python -V
Python 2.7.15+

$ python3 -V
Python 3.6.8

$ python3.7 -V
Python 3.7.5

 

mod_wsgi

그냥 django를 서버로 바로 돌렸으면 좋았겠지만, 제가 사용하는 가상 머신 서버에는 이미 여러 서비스가 동작하고 있습니다. apache httpd가 80 포트를 이미 사용하고 있기 때문에 django를 서버로 돌리면서 80 포트를 사용할 수 없습니다. 물론 django를 서버 모드로 사용하면서 80 포트를 사용하는 방법이 있긴 합니다. apache에 proxy 설정을 해 주면 됩니다. 하지만 mod_wsgi를 사용하면 django를 서버로 돌리지 않더라도 apache를 통해 서비스를 할 수 있어서 mod_wsgi를 사용했는데요. 문제는 python 버전이 바뀌면 mod_wsgi도 다시 설정해 주어야 하더군요.

소스코드를 직접 빌드해서 설치해 주었는데요. 대략 아래와 같은 순서로 빌드할 수 있습니다.

$ wget https://github.com/GrahamDumpleton/mod_wsgi/archive/4.7.1.tar.gz
$ tar xvfz 4.7.1.tar.gz
$ ./configure --with-python=/usr/bin/python3.7
$ make
$ sudo make install

빌드를 하면 mod_wsgi.so가 설치됩니다.

$ sudo make install
/usr/bin/apxs2 -i -S LIBEXECDIR=/usr/lib/apache2/modules -n 'mod_wsgi' src/server/mod_wsgi.la
/usr/share/apache2/build/instdso.sh SH_LIBTOOL='/usr/share/apr-1.0/build/libtool' src/server/mod_wsgi.la /usr/lib/apache2/modules
/usr/share/apr-1.0/build/libtool --mode=install install src/server/mod_wsgi.la /usr/lib/apache2/modules/
libtool: install: install src/server/.libs/mod_wsgi.so /usr/lib/apache2/modules/mod_wsgi.so
libtool: install: install src/server/.libs/mod_wsgi.lai /usr/lib/apache2/modules/mod_wsgi.la
libtool: finish: PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/sbin" ldconfig -n /usr/lib/apache2/modules
----------------------------------------------------------------------
Libraries have been installed in:
   /usr/lib/apache2/modules

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the '-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the 'LD_LIBRARY_PATH' environment variable
     during execution
   - add LIBDIR to the 'LD_RUN_PATH' environment variable
     during linking
   - use the '-Wl,-rpath -Wl,LIBDIR' linker flag
   - have your system administrator add LIBDIR to '/etc/ld.so.conf'

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------
chmod 644 /usr/lib/apache2/modules/mod_wsgi.so

/usr/lib/apache2/modules/mod_wsgi.so경로에 설치되는데요. 이 경로를 복사합니다.

그리고 /etc/apache2/mods-available/wsgi.load 파일을 수정합니다.

LoadModule wsgi_module "/usr/lib/apache2/modules/mod_wsgi.so"

기존에는 아래처럼 되어 있었습니다.

LoadModule wsgi_module "/usr/lib/apache2/modules/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so"

 

잘 된 내용들을 정리했지만 python 설치 라던지, apt 설치하려는데 /boot 영역 용량 부족, openssl 문제 등 여러 삽질이 있었는데 여기서는 생략했습니다. 다음에 또 정리할 일이 생기겠죠. 아무튼 이번 글은 여기까지~

 

반응형
Comments