Flask + IIS 로 윈도우에서 서비스하기

Flask로 만든 라이센스서버를 윈도우에 올려보기로 한다.

테스트할 환경은 다음과 같다.

  • OS : Microsoft Windows 10
  • Python : 3.6.8
  • Flask로 작성된 어플리케이션

 

Flask와 IIS

원래는 Flask로 만들었으니 IIS에 붙이려고 했다. 그런데 그게 쉽지 않았다. IIS에 온갖 설정과 에러와 싸우며 조금씩 전진했지만 나는 지쳐갔고 정말 이게 최선인가…? 하는 생각이 들기 시작했다. 어차피 플라스크만으로도 괜찮은 웹서버 아니었던가? 굳이 IIS와 연동이 왜 필요한가? 에서 답을 찾지 못했다.

아파치나 nginx와 연동도 있었지만 이건 결국 플라스크로 만든 어플리케이션을 띄워놓은 상태에서 웹으로 들어오는 요청만 프록시 처리해주는 방식이라 더 의미 없는 것 같았다.

그래서 이걸 아예 윈도우서비스로 올릴 수 있으면 어떨까 싶었다.

 

Web.config 파일 생성

https://docs.microsoft.com/ko-kr/visualstudio/python/configure-web-apps-for-iis-windows?view=vs-2019

웹페이지를 보며 설정한다.

간단하게 web.config 파일만 생성해주면 되었다.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <add	name="PythonHandler"
            path="*"
            verb="*"
            modules="FastCgiModule"
            scriptProcessor="C:\Python\Python36\python.exe|C:\Python\Python36\Lib\site-packages\wfastcgi.py"
            resourceType="Unspecified"
            requireAccess="Script" />
    </handlers>
    
  </system.webServer>
  
  <appSettings>
      <add key="PYTHONPATH" value="D:\license_server"/>
      <!-- The handler here is specific to Bottle; see the next section. -->
      <add key="WSGI_HANDLER" value="runserver.application"/>
      <add key="WSGI_LOG" value="D:\logs\wfastcgi.log"/>
  </appSettings>
</configuration>

 

wfastcgi-enable 실행

cmd를 관리자 권한으로 열고, 파이썬 프로그램이 있는 곳에 가서 wfastcgi-enable 을 실행해준다.

 

IIS에서 사이트를 생성하고 접속해본다.

 

파일을 생성하고 실행하니 이상하게도 config 파일을 읽어오지 못하는 문제가 발생했다. 경로도 모두 맞는데 파일을 읽지 못하는 현상.

확인해봤더니 root 경로를 잘못 잡고 있었다. 경로 밑에 config 파일을 넣어주니 해결

 

참고자료

apache 2.4 + flask 설정방법

아파치에서 Flask로 만들어진 어플리케이션을 작동하기 위한 방법을 정리해둔다.

 

에러메시지는

[Mon Jul 03 19:42:27.334280 2017] [:error] [pid 14570] [client 59.10.233.103:63211] Traceback (most recent call last):
[Mon Jul 03 19:42:27.334301 2017] [:error] [pid 14570] [client 59.10.233.103:63211] File "/home/viper9/python_test/VeloWeight.wsgi", line 7, in <module>
[Mon Jul 03 19:42:27.334349 2017] [:error] [pid 14570] [client 59.10.233.103:63211] from hello import app as application
[Mon Jul 03 19:42:27.334364 2017] [:error] [pid 14570] [client 59.10.233.103:63211] File "/home/viper9/python_test/hello.py", line 1, in <module>
[Mon Jul 03 19:42:27.334392 2017] [:error] [pid 14570] [client 59.10.233.103:63211] from flask import Flask
[Mon Jul 03 19:42:27.334409 2017] [:error] [pid 14570] [client 59.10.233.103:63211] ImportError: No module named flask
[Mon Jul 03 19:42:27.432767 2017] [:error] [pid 14538] [client 59.10.233.103:63210] mod_wsgi (pid=14538): Target WSGI script '/home/viper9/python_test/VeloWeight.wsgi' cannot be loaded as Python module., referer: http://python.83rpm.com/
[Mon Jul 03 19:42:27.432821 2017] [:error] [pid 14538] [client 59.10.233.103:63210] mod_wsgi (pid=14538): Exception occurred processing WSGI script '/home/viper9/python_test/VeloWeight.wsgi'., referer: http://python.83rpm.com/
[Mon Jul 03 19:42:27.432848 2017] [:error] [pid 14538] [client 59.10.233.103:63210] Traceback (most recent call last):, referer: http://python.83rpm.com/
[Mon Jul 03 19:42:27.432870 2017] [:error] [pid 14538] [client 59.10.233.103:63210] File "/home/viper9/python_test/VeloWeight.wsgi", line 7, in <module>, referer: http://python.83rpm.com/
[Mon Jul 03 19:42:27.432904 2017] [:error] [pid 14538] [client 59.10.233.103:63210] from hello import app as application, referer: http://python.83rpm.com/
[Mon Jul 03 19:42:27.432914 2017] [:error] [pid 14538] [client 59.10.233.103:63210] File "/home/viper9/python_test/hello.py", line 1, in <module>, referer: http://python.83rpm.com/
[Mon Jul 03 19:42:27.432928 2017] [:error] [pid 14538] [client 59.10.233.103:63210] from flask import Flask, referer: http://python.83rpm.com/
[Mon Jul 03 19:42:27.432963 2017] [:error] [pid 14538] [client 59.10.233.103:63210] ImportError: No module named flask, referer: http://python.83rpm.com/

http://flask.pocoo.org/docs/0.12/deploying/mod_wsgi/ 를 읽어보니 다음과 같이 써있었다.

 

Working with Virtual Environments
Virtual environments have the advantage that they never install the required dependencies system wide so you have a better control over what is used where. If you want to use a virtual environment with mod_wsgi you have to modify your .wsgi file slightly.

Add the following lines to the top of your .wsgi file:

activate_this = ‘/path/to/env/bin/activate_this.py’
execfile(activate_this, dict(file=activate_this))
For Python 3 add the following lines to the top of your .wsgi file:

activate_this = ‘/path/to/env/bin/activate_this.py’
with open(activate_this) as file_:
exec(file_.read(), dict(file=activate_this))

 

execfile(activate_this, dict(file=activate_this)) 를 삭제하고

 

with open(activate_this) as file_:
exec(file_.read(), dict(file=activate_this))

 

를 추가했다.

 

하지만 다시 실행해도 같은 에러…

 

wsgi 파일을 다음과 같이 수정했다.

import os
import sys
import site

site.addsitedir('/home/viper9/python_test/venv/lib64/python3.4/site-packages')

sys.path.insert(0, '/home/viper9/python_test')

activate_this = '/home/viper9/python_test/venv/bin/activate_this.py'
with open(activate_this) as file_:
exec(file_.read(), dict(file=activate_this))

from hello import app as application

 

MySQL 에러가 난다면 다음의 패키지를 설치한다.

yum install MySQL-python

 

해결했더니 그 다음 에러…

UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xae in position 8: ordinal not in range(128)

 

https://libsora.so/posts/python-hangul/ 를 찾아보니 인코딩의 문제라고 한다. 문서를 보고 해결. .wsgi 에 설정을 추가했다.

reload(sys)
sys.setdefaultencoding('utf-8')

그런데… 그래도 해결이 안된다… 아 힘들다. 다시 이런저런 정보를 찾아헤메이다 로그를 다시 읽어보니 DB를 사용하는 곳에서만 에러가 났다. DB에서 데이터 가져올 때 문제가 있구나.. 라는 생각이 들어 DB 설정을 확인했더니 utf-8로 이미 다 설정되어 있었다. 코드도 UTF-8이고 DB도 UTF-8인데 데이터 가져오는데 문제가 있다면 커넥션 자체에서 캐릭터셋을 지정해주지 않아서 그런 것 같았다. 다시 검색을 해보니 다음 문서를 발견 https://stackoverflow.com/questions/10819192/sqlalchemy-result-for-utf-8-column-is-of-type-str-why create_engine() 함수를 쓸 때

create_engine('mysql+mysqldb:///mydb?charset=utf8')

처럼 사용하라는 것이었다. 이 설정을 추가해주니 드디어 페이지가 정확하게 떴다. 아이고 힘들다…

Google Breakpad 설치 (2)

gyp 파일을 다 실행하고 나면 솔루션 파일과 프로젝트 파일 등이 생겨난다. 비주얼스튜디오로 솔루션 파일을 열어보면 다음과 같이 여러개의 프로젝트가 솔루션 안에 들어있다.

K-007

맨 밑에 build_all 프로젝트를 빌드해보면…

84개의 오류와 28개의 경고로 빌드가 안된다. 뭐 어차피 기대도 안했다.

에러메시지를 보면

#include "testing/gtest/include/gtest/gtest.h"
#include "testing/include/gmock/gmock.h"

이 부분에서부터 에러가 시작된다. gtest와 gmock이 필요하다고 한다. 이건 아마 외부라이브러리인 모양.

이 패키지들은 https://github.com/google/googletest 에서 받을 수 있다. 이 레포지토리를 git으로 클론한다. 다운로드 받으면 googlemock과 googletest다 들어있으며, 각 디렉토리에 msvc 라는 디렉토리가 있고 여기에 비주얼스튜디오로 열 수 있는 솔루션 파일과 프로젝트 파일들이 들어있다.

솔루션 파일들을 열어서 실행해보면 .lib 파일들이 생성된다. 이것들은 지금 당장은 필요 없다.

 

이제 이 파일들을 구조에 맞게 넣어줘야한다. 이걸 어떻게 해야하는지 몰라서 한참 찾았다.

https://github.com/Mendeley/breakpad

이 사람이 디렉토리 구조를 이미 만들어서 넣어놨길래 그대로 참고했다. (아마 이 사람은 브레이크패드에 맞도록 모든 라이브러리 파일을 다 넣어서 올려놓은듯하다. 이 소스를 받아다가 사용하면 잘될꺼 같기도하다.)

여기서부터 문제가 있는데, googlemock과 googletest 디렉토리를 구글브레이크패드 폴더에 복사해넣어줘야 한다. 그런데 내 경우에는, 회사컴퓨터에서 할 때와, 내 컴퓨터에서 했을 때 경로가 달랐다.

회사컴퓨터에서는… 구글 브레이크패드 디렉토리 중 src 디렉토리 밑에 testing 디렉토리를 만들고 거기에 googlemock 디렉토리 내용 전체를 복사해서 넣는다. 그리고 src/testing 디렉토리 밑에 gtest 디렉토리를 만들고 거기에는 googletest 디렉토리 내용 전체를 복사해서 넣는다.

집 컴퓨터에서는… 구글 브레이크 패드 디렉토리 중 src 디렉토리 밑에 testing 디렉토리를 만들고 거기에 googlemock과 googletest 디렉토리 두개를 그대로 복사해넣었다.

 

이제 구글 브레이크패드 솔루션 파일을 열고 build_all 프로젝트를 빌드해보면…

안된다.

 

오류가 난다. 오류내용은

C4091 'typedef ': 변수를 선언하지 않으면 '' 왼쪽은 무시됩니다.
C2220 경고가 오류로 처리되어 생성된 'object' 파일이 없습니다.

해당 코드는 다음과 같이 되어있다.

typedef enum {
    hdBase = 0, // root directory for dbghelp
    hdSym,      // where symbols are stored
    hdSrc,      // where source is stored
    hdMax       // end marker
};

enum인데 이름이 정의되지 않은 상태로 typedef가 되었기 때문에 나는 에러이다.

이걸 검색해보니 다음과 같은 내용을 찾았다.

https://stackoverflow.com/questions/913344/how-can-i-remove-the-vs-warning-c4091-typedef-ignored-on-left-of-spreadsh

typedef를 그냥 삭제해버리랜다. 삭제하려고 봤더니…

이 오류가 나는건, C:\Program Files (x86)\Windows Kits\8.1\Include\um\DbgHelp.h 파일이었다. C++ 라이브러리를 수정할 수는 없는 노릇… ‘프로젝트 속성’의 ‘구성 속성’ -> ‘C/C++’ -> ‘고급’을 찾아가 ‘특정 경고 사용 안 함’ 에 4091을 추가했다. 이제 빌드가 된다.

같은 에러가 나는 프로젝트를 찾아서 전부 위처럼 4091 에러에 대한 경고무시를 설정해줘야한다.

이렇게 또 build_all 을 해봤더니 또 오류가 난다.

프로젝트 중 unittests 에 있는 processor_bits 프로젝트가 계속 에러가 나는 것이었다. 경고를 전부 오류 처리해버리기에 빌드가 되지 않았다. 이것도 4091 에러처럼 4267, 4366 을 경고무시에 추가한다.

이제 다시 build_all 프로젝트를 빌드해본다.

또 오류가 난다.

unittest 에 있는 client_tests 프로젝트에서 에러가 났다. 마찬가지로 경고를 오류로 처리해서 나는 에러. 4389, 4312, 4267 을 경고무시로 넣어준다.

다시 build_all 프로젝트를 빌드해본다.

드디어 아무 에러 없이 성공.

이제 빌드된 구글브레이크패드를 이용해서 실제 사용하는 방법을 찾아봐야겠다.

Google Breakpad 설치 (1)

Google Breakpad를 사용하기 위한 방법에 대해 고생했던 것을 정리한다.

윈도우와 리눅스에서 동시에 사용할 수 있는 서버프로그램을 개발하고 있는데 윈도우에서야 미니덤프를 이용하여 덤프를 남기면 되지만 리눅스에서는 coredump라는 생소한 시스템을 이용해야해서 아예 크로스플랫폼 덤프 시스템을 찾다가 구글브레이크패드를 이용해봐야겠다는 생각에 시작했다.

https://chromium.googlesource.com/breakpad/breakpad 로 이동한다. 많은 블로그에서 http://google-breakpad.googlecode.com/svn/trunk 에서 체크아웃 받으라고 나와있지만 이것은 옛날 정보이다. 현재를 기준으로 사이트는 이동되었으며 SVN이 아니라 GIT을 이용해야 소스를 받을 수 있다.

GIT을 이용하면 되긴하나 귀찮으므로 master 브랜치를 선택하고 tgz로 압축된 파일을 받는다. 7zip을 이용하여 압축파일의 압축을 해제한다. 윈도우에서는 tgz 파일을 풀어서 tar 파일을 만들고 다시 또 한번 아카이빙을 풀어야한다. 물론 7zip 하나로 다 가능하다.

프로그램 설명서를 보기 위해 doc 폴더로 이동을 하면…. 아오… 마크다운 형식의 .md 파일만 잔뜩 들어있다. 브라우저로 볼 수가 없으므로 귀찮아서 그냥 구글 브레이크패드 홈페이지의 도큐먼트를 읽어보면 된다.

….근데 모르겠다.

대충 다른 블로그를 찾아보니 gyp 라는 시스템으로 비주얼스튜디오 솔루션 파일을 생성하면 되고…. gyp는 오픈소스이고… 구글 브레이크패드 소스를 받으면 포함되어 있단다. 근데 내가 보기에는 아무리 찾아도 gyp 라는 시스템이 포함되어 있진 않은 것 같다.

구글에 찾아보니 https://chromium.googlesource.com/external/gyp 에 가면 받을 수 있덴다.

가보니 또 git으로 받으라고 한다. 그냥 tgz 파일을 받고 압축을 푼다. 이 프로그램은 홈페이지에 도큐먼트도 없고 도움말도 없다. 뭐 어쩌라는건지…?

한참 애먹은 끝에… 일단 파이선을 설치하고(일단 최신버전인 3.5.2로 설치했다.), cmd 를 관리자권한으로 열고, python setup.py install 을 실행하면 된다는걸 알아냈다. 아오 짜증… 여튼 명령어를 입력하면 뭔가 텍스트가 촤르르륵 올라간다.

자 이제 다시 구글 브레이크패드를 다운 받은 폴더로 이동해서… src/build 에 있는 all.gyp를 실행하기 위해 gyp all.gyp 를 입력한다.

…..는 실패. 문법 오류가 있다고 한다.

그럼 다시 src/client/windows 의 breakpad_client.gyp 를 실행해본다.

…는 실패. 문법 오류가 있다고 한다.

파이선버전 문제인가 싶어서 3.5.2 버전을 다 지우고 2.7.12 버전으로 다시 설치하고 아까 all.gyp 명령을 다시 실행해본다.

안된다. 파이선을 재설치하는 과정에서 gyp가 다 삭제되었다. 다시 gyp를 설치한다.

다시 해봤는데 똑같다… 아오 힘들어.

http://yardbirds.tistory.com/107 를 보니

src\client\windows 폴더에서 ..\..\tools\gyp\gyp.bat breakpad_client.gyp 를 실행하면 솔루션 파일과 프로젝트 파일이 생성되는 것을 볼 수 있다.

라고 한다. 해봤다.

D:\Library\google-breakpad\src\client\windows>d:\Library\gyp-master\gyp.bat breakpad_client.gyp
gyp: Cycles in .gyp file dependency graph detected:
Cycle: breakpad_client.gyp -> sender\crash_report_sender.gyp -> breakpad_client.gyp
Cycle: unittests\client_tests.gyp -> breakpad_client.gyp -> unittests\client_tests.gyp
Cycle: unittests\client_tests.gyp -> crash_generation\crash_generation.gyp -> breakpad_client.gyp -> unittests\client_tests.gyp
Cycle: breakpad_client.gyp -> crash_generation\crash_generation.gyp -> breakpad_client.gyp
Cycle: unittests\client_tests.gyp -> handler\exception_handler.gyp -> crash_generation\crash_generation.gyp -> breakpad_client.gyp -> unittests\client_tests.gyp
Cycle: breakpad_client.gyp -> handler\exception_handler.gyp -> crash_generation\crash_generation.gyp -> breakpad_client.gyp
Cycle: breakpad_client.gyp -> tests\crash_generation_app\crash_generation_app.gyp -> handler\exception_handler.gyp -> crash_generation\crash_generation.gyp -> breakpad_client.gyp

갑자기 무슨 사이클을 돈다는 개소리를 하면서 안된다. 구글에서 Cycles in .gyp file dependency graph detected 라는 문장으로다시 검색.

http://stackoverflow.com/questions/2925094/how-to-build-google-breakpad 를 보니 –no-circular-check 옵션을 붙이면 된단다. 옵션을 붙였더니 그제서야 비주얼스튜디오 솔루션 파일이 생성되었다.

아이고 힘들다…

 

2018년 12월 25일 추가

위 작업에서 파이썬 3.5에서는 확실히 되지 않았다. 파이썬 2.7로 하니 제대로 작동하였다. 반드시 파이썬 2.7로 해볼 것. 파이썬은 도대체 왜 이따위로 만들어져 있는건지 정말 이해가 안간다…

Python stdlib source files not found 에러 해결방법

파이썬 개발환경을 만들기 위해 이클립스에 PyDev를 설치하고 환경을 맞추다보니 에러가 생긴다.

문제 화면은 다음과 같다.

Python stdlib source files not found. 라는 에러인데… (파이썬도 stdlib 라는 라이브러리가 있나보다. 신기하다.) 맥에는 파이썬이 기본으로 설치되어 있는데 왜 안될까 해서 쉘에서 설치여부를 확인해봐도 여전히 설치되어 있음. 미치고 환장할 일이다.

구글을 한참 뒤지고 stackoverflow로 한참 뒤지다보니 여러가지 해결방법이 보인다. 파이썬 홈페이지 가서 파이썬 패키지를 다시 깔면 된다고 하는데 이렇게 하면 파이썬 버전이 3버전대로 업그레이드 되는게 문제다. 난 지금 있는 맥의 환경이 좋은데다가 앞으로 할 작업도 2.7 이하 버전이 필요하기 때문에 이 방법은 패쓰.

그러다가 한가지 URL을 찾았다.

http://stackoverflow.com/questions/11702139/pydev-debugger-unable-to-find-real-location-for-python-2-7-after-os-10-8-upgrad

Mac OSX 10.8로 업그레이드 한 경우에는 Command Line Tools를 설치해야한다는 것. 나도 10.7에서 업그레이드해서 설치한 것이라 이 링크가 도움이 될 것 같았다. 밑에 어떤 사람이 리플로 Xcode가 설치되어 있다면 Preference에 Download에 가면 된다고 해서 Xcode를 켜고 가보니 정말로 Install 버튼이 활성화 되어 있었다. 이것을 설치하고 나니 위 에러가 싹 사라졌다.

만약에 Xcode가 없는 사람이라면 https://developer.apple.com/downloads/index.action?=command%20line%20tools 에서 다운로드 받을 수 있다.

다시 이클립스를 켜고 PyDev 프로젝트를 생성해보니 잘 된다! 이로써 파이썬 2.7 설치환경은 완료.

이클립스에 PyDev 설치하기

파이썬을 개발하기 위해 이클립스에 PyDev를 설치한다.

PyDev가 실행될 수 있는 환경은 http://www.pydev.org/download.html 에 자세히 나와있다. 별로 특이한 점 없고 이클립스를 사용해왔던 환경이라면 이정도는 무난히 충족되는 환경일거라고 생각한다.

설치과정은 에 http://khmirage.tistory.com/404 잘 나와있다. 이분도 맥에서 이클립스를 쓰시는구나. 🙂

쉽게 이클립스에서 인스톨 URL에 http://pydev.org/updates 만 입력해주면 된다는 것만 기억하면 된다. 중요한건 Aptana를 쓸 때와 이클립스를 쓸 때 등등 여러가지 환경에서 설치URL이 틀리다. 이런 귀찮음을 방지하기 위해서는 역시 그냥 오리지널 이클립스만 쓰는 것이 제일 나은 것 같다.

여튼 인스톨 URL만 잘 입력해주면 별로 어렵지 않게 설치된다.

중요한 점 하나. 중간에 인증관련한 화면이 한번 나오는데 체크박스에 꼭 체크를 해줘야한다. 안 그러면 설치가 중지된다. ㅡㅡ;; 이클립스 플러그인 중에 이런 화면은 또 처음 봤다.

잘 설치가 되었다면 새 프로젝트 생성할 때 PyDev라는 항목이 생긴다.

Python에서 MySQL 연동

일단 서버에 파이썬을 설치한다. 내 경우에는 CentOS 6.3에 파이썬은 2.6 버전이다. yum으로 설치할 수 있는 가장 최신 버전.

mysql.com에서 파이썬 커넥터를 찾는다. 현재는 http://www.mysql.com/downloads/connector/python/#downloads 에서 찾을 수 있다. 리눅스에서 설치할 것이므로 Platform Independent 버전을 다운로드 받아야한다.

다운로드 받은 파일을 압축을 폴면 디렉토리 하나와 그 안에 여러개의 파일들이 들어가 있다.

폴더 안에 들어가서 python setup.py build 명령을 준다. 파일들이 복사된다는 메시지들이 쭉 뜬다.

python setup.py install 명령을 내린다. 역시 파일들이 복사된다는 메시지들이 쭉 뜬다.

python 명령을 치고 파이썬 쉘에서 import MySQLdb 를 입력해본다. 별 문제가 없다면 설치 완료.