Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 2개 있습니다.)
(시리즈 글이 3개 있습니다.)
스크립트: 23. 파이썬 - WSGI를 만족하는 최소한의 구현 코드 및 PyCharm에서의 디버깅 방법
; https://www.sysnet.pe.kr/2/0/12794

스크립트: 64. 파이썬 - ASGI를 만족하는 최소한의 구현 코드
; https://www.sysnet.pe.kr/2/0/13633

스크립트: 65. 파이썬 - asgi 버전(2, 3)에 따라 달라지는 uvicorn 호스팅
; https://www.sysnet.pe.kr/2/0/13642




파이썬 - WSGI를 만족하는 최소한의 구현 코드 및 PyCharm에서의 디버깅 방법

uwsgi나 gunicorn이,

파이썬 - 윈도우 환경에서 개발한 Django 앱을 WSL 환경의 uwsgi를 이용해 실행
; https://www.sysnet.pe.kr/2/0/12772

파이썬 - 윈도우 환경에서 개발한 Django 앱을 WSL 환경의 gunicorn을 이용해 실행
; https://www.sysnet.pe.kr/2/0/12775

Django App을 동일하게 실행시킬 수 있는 건 2개의 응용 프로그램 사이에 WSGI라는 공통 규약이 있기 때문입니다.

PEP 333 -- Python Web Server Gateway Interface v1.0
; https://www.python.org/dev/peps/pep-0333/

PEP 3333 -- Python Web Server Gateway Interface v1.0.1
; https://www.python.org/dev/peps/pep-3333/

그렇다는 건, 꼭 Django를 사용하지 않더라도 저 WSGI 규약만 맞춰주면 우리가 만든 앱을 uwsgi/gunicorn을 이용해 동일하게 실행시킬 수 있다는 것을 의미합니다.

실제로 "PEP 3333 -- Python Web Server Gateway Interface v1.0.1" 문서에 실린 코드가 바로 WSGI 규약을 만족하는 최소한의 구현 코드입니다.

# main.py

HELLO_WORLD = b"Hello world!\n"


def simple_app(environ, start_response):
    """Simplest possible application object"""
    status = '200 OK'
    response_headers = [('Content-type', 'text/plain')]
    start_response(status, response_headers)
    return [HELLO_WORLD]


application = simple_app

(닷넷과 비교하면 ASP.NET의 Route-to-code 방식과 유사합니다. ^^)

저렇게만 만들어 두면 이제 다음과 같이 gunicorn을 사용해 실행하는 것이 가능합니다.

$ gunicorn --bind 0.0.0.0:18090 main
[2021-08-18 18:14:02 +0900] [1670] [INFO] Starting gunicorn 20.0.4
[2021-08-18 18:14:02 +0900] [1670] [INFO] Listening at: http://0.0.0.0:18090 (1670)
[2021-08-18 18:14:02 +0900] [1670] [INFO] Using worker: sync
[2021-08-18 18:14:02 +0900] [1672] [INFO] Booting worker with pid: 1672

즉, uwsgi/gunicorn은 파이썬 애플리케이션으로부터 무조건 "application" 전역 변수에 설정된 웹 프레임워크 인스턴스를 받아와 Request/Response 처리를 넘겨주는 것입니다. 사실 여기서 application은 기본값에 불과하므로 이것을 정의하지 않는다면 다음과 같이 직접 simple_app을 지정하는 것도 가능합니다.

$ gunicorn --bind 0.0.0.0:18090 main:simple_app

어쨌든 이렇게 준비를 마쳤으면, 웹 브라우저에서 "http://localhost:18090"으로 접속해 "Hello world!"라는 문자열을 볼 수 있습니다.




그런데, 저렇게 구현한 코드를 어떻게 디버깅해야 하는 걸까요? 가령, PyCharm IDE 같은 환경에서 main.py의 simple_app 함수를 실행하는 순간 디버깅하고 싶으면 어떻게 해야 하냐는 것입니다.

(Visual Studio를 사용하는) 윈도우 개발자라면 이런 경우 시작 프로세스를 "gunicorn"으로, 명령행 인자에 "--bind 0.0.0.0:18090 main"으로 지정하고 F5 키를 누르면 실행 시 디버깅이 될 것이라는... 사용자 경험을 가지고 있습니다.

하지만, PyCharm의 경우에는 무조건 "Python Interpreter"의 'python'이 시작 프로세스로 지정돼 있어야 하고 이후의 명령행을 지정하는 식입니다. 이로 인해 시작 프로세스가 gunicorn/uwsgi라면 디버깅이 안 되는 것입니다.

이런 때 사용할 수 있는 서버가 바로 wsgiref입니다.

wsgiref — WSGI Utilities and Reference Implementation
; https://docs.python.org/3/library/wsgiref.html#module-wsgiref.simple_server

따라서 위의 문서에 나온 예제 코드에 따라 다음과 같이 간단하게 (uwsgi/gunicorn을 대체하는) Web Server를 python 코드로 완성할 수 있습니다.

# runserver.py

from wsgiref.validate import validator
from wsgiref.simple_server import make_server
import main

validator_app = validator(main.simple_app)

with make_server('', 18090, validator_app) as httpd:
    print("Listening on port 18090....")
    httpd.serve_forever()

이제 PyCharm의 "Run/Debug Configuration"에서 "Script path"를 "...[프로젝트 경로]...\runserver.py"로 지정하고 실행하면 simple_app의 코드에 BP를 걸고 디버깅을 할 수 있습니다. (PyCharm과 관련한 디버깅 방법은 이후로도 쭉 소개하겠습니다. ^^)

아울러 아래의 글들도 참고하시고. ^^

Quickstart uwsgi
; https://brunch.co.kr/@ddangdol/8

wsgi를 왜 쓰나요
; https://uiandwe.tistory.com/1268

[python] 서버의 기본 동작 방식
; https://uiandwe.tistory.com/1240




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 8/20/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2021-08-24 10시16분
정성태

... [196]  197  198 
NoWriterDateCnt.TitleFile(s)
81정성태12/31/200421775    답변글 VS.NET IDE: 12.2. Tier 컴퓨터를 모두 영문으로 재구성
109정성태3/4/200516866    답변글 VS.NET IDE: 12.3. [보완] MS 공식 아티클 - Installing the December CTP Release of Visual Studio Team System
73정성태11/14/200518615.NET Framework: 19. VS.NET 2005 Team Foundation Server 설치오류 - 26204 예외
72정성태12/26/200420119.NET Framework: 18. .NET Framework 2.0 Beta 설치 후에 Windows SharePoint Service 오류 [1]
136정성태3/31/200520141    답변글 .NET Framework: 18.1. Windows Sharepoint Services 를 설치한 이후 ASP.NET 오류 문제
71정성태12/26/200418260VS.NET IDE: 11. SQL Server 2005 Beta 2 를 네트워크 드라이브로부터 설치시 오류
70정성태12/26/200421193VS.NET IDE: 10. WSS 설치 후 localhost 접근 보안 오류
69정성태12/5/200418288VS.NET IDE: 9. 다른 컴퓨터(방화벽 설치)에 설치된 SQL Server에 통합 인증을 할 때 필요한 포트
68정성태10/31/200423110.NET Framework: 17. Win32_NTLogEvent를 c#에서 wmi 쿼리할 때..에러..
67정성태10/22/200420338COM 개체 관련: 12. Microsoft.XMLHTTP 개체에서 Microsoft.XMLDOM 개체를 전송할 때 charset 지정 문제?
66정성태10/16/200421588.NET Framework: 16. [닷넷 리모팅] 프록시가 죽은 것을 원격 개체가 알 수 있는 방법은?
65정성태10/16/200420516VS.NET IDE: 8. Windows 가상 메모리 사용 해제
64정성태10/3/200424246.NET Framework: 15. ASP.NET에서 .NET COM+ 개체 등록 시 "Local System"이어야 하는 이유.
63정성태10/3/200424289.NET Framework: 14. Response.Cookies.Clear는 기존 설정된 Cookie 헤더를 삭제하는 것이 아닙니다.
62정성태10/3/200423409기타: 7. DB 트랜잭션에서 Lock이 걸릴 수 있는 전형적인 예.
61정성태10/3/200422829.NET Framework: 13. Main 메서드에 붙은 STAThread 의미
60정성태10/3/200421625.NET Framework: 12. IDispatch::GetIDsOfNames 역변환 메서드 작성 힌트 ( DISPID 로 메서드 이름 알아내는 것 )
58정성태10/3/200424762.NET Framework: 11. HttpContext의 간략이해
56정성태10/3/200421178.NET Framework: 10. [.NET 리모팅] 원격개체를 호출한 클라이언트의 연결이 유효한지 판단하는 방법.
55정성태10/3/200421972COM 개체 관련: 11. 내가 생각해 보는 COM의 현재 위치
54정성태8/30/200427566VC++: 10. 내가 생각해 보는 MFC OCX와 ATL DLL에 선택 기준
53정성태11/20/200526864VC++: 9. CFtpFileFind/FtpFileFind가 일부 Unix FTP 서버에서 목록을 제대로 못 가져오는 문제
184정성태11/23/200520638    답변글 VC++: 9.1. FTP 관련 토픽파일 다운로드1
51정성태6/24/200425749VC++: 8. BSTR 메모리 할당 및 해제(MSDN Library 발췌) [1]
50정성태6/16/200418970기타: 6. 1차 데스크톱 컴퓨터 사양
49정성태6/16/200419375기타: 5. 53만 원대 Second PC 마련. ^^
... [196]  197  198