Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 

(시리즈 글이 11개 있습니다.)
개발 환경 구성: 592. JetBrains의 IDE(예를 들어, PyCharm)에서 Visual Studio 키보드 매핑 적용
; https://www.sysnet.pe.kr/2/0/12752

개발 환경 구성: 595. PyCharm - WSL과 연동해 Django App을 윈도우에서 리눅스 대상으로 개발
; https://www.sysnet.pe.kr/2/0/12773

개발 환경 구성: 597. PyCharm - 윈도우 환경에서 WSL을 이용해 파이썬 앱 개발/디버깅하는 방법
; https://www.sysnet.pe.kr/2/0/12789

개발 환경 구성: 598. PyCharm - 원격 프로세스를 디버그하는 방법
; https://www.sysnet.pe.kr/2/0/12798

개발 환경 구성: 599. PyCharm - (반대로) 원격 프로세스가 PyCharm에 디버그 연결하는 방법
; https://www.sysnet.pe.kr/2/0/12800

개발 환경 구성: 601. PyCharm - 다중 프로세스 디버깅 방법
; https://www.sysnet.pe.kr/2/0/12806

스크립트: 26. 파이썬 - PyCharm을 이용한 fork 디버그 방법
; https://www.sysnet.pe.kr/2/0/12823

개발 환경 구성: 603. GoLand - WSL 환경과 연동
; https://www.sysnet.pe.kr/2/0/12825

개발 환경 구성: 673. JetBrains IDE에서 "Squash Commits..." 메뉴가 비활성화된 경우
; https://www.sysnet.pe.kr/2/0/13318

개발 환경 구성: 679. PyCharm(을 비롯해 JetBrains에 속한 여타) IDE에서 내부 Window들의 탭이 없어진 경우
; https://www.sysnet.pe.kr/2/0/13369

개발 환경 구성: 697. GoLand에서 ldflags 지정 방법
; https://www.sysnet.pe.kr/2/0/13489




PyCharm - (반대로) 원격 프로세스가 PyCharm에 디버그 연결하는 방법

일반적으로 비주얼 스튜디오에 익숙한 사용자라면 원격 디버깅이라고 할 때 이전에 설명했던,

PyCharm - 원격 프로세스를 디버그하는 방법
; https://www.sysnet.pe.kr/2/0/12798

방식의 디버깅만을 연상하게 됩니다. 그런데, 특이하게도 PyCharm의 경우 프로세스 측에서 PyCharm IDE로 디버그 연결을 하는 방법을 함께 제공합니다.

이런 문제는, 아마도 지난 글에 소개한,

파이썬 - WSGI를 만족하는 최소한의 구현 코드 및 PyCharm에서의 디버깅 방법
; https://www.sysnet.pe.kr/2/0/12794

simple_app과 같은 앱을 uwsgi/gunicorn 등에서 호스팅할 때 디버깅을 원한다면 사용할 수 있는 대안으로써 제공되는 듯합니다. 이와 관련된 공식 문서도 있지만,

debugging a uwsgi python application using pycharm
; https://stackoverflow.com/questions/21257568/debugging-a-uwsgi-python-application-using-pycharm

Remote debugging with the Python remote debug server configuration
; https://www.jetbrains.com/help/pycharm/remote-debugging-with-product.html#remote-debug-config

역시 문서보다 ^^ 직접 상황에 따른 예를 드는 것이 더 이해가 빠르겠지요. 이번에도 "PyCharm - 원격 프로세스를 디버그하는 방법"에서처럼 원격 PC가 있어야겠지만 어차피 설정은 모두 동일하므로 WSL 환경에서 테스트를 하겠습니다.

즉, 원격 PC(또는 WSL)에서 실행한 uwsgi/gunicorn 프로세스에서 호스팅되는 Python App을 디버깅하는 것을 가정하고 설명하겠습니다. ^^




우선, PyCharm IDE에서 새로운 "Run/Debug Configuration"을 "Python Debug Server" 유형으로,

passive_remote_debug_1.png

포트와 IDE host name을 입력해 생성합니다. (이 글에서는 WSL 환경이므로 localhost와 임의의 포트를 지정했습니다. 일반적인 상황이라면, "0.0.0.0"으로 AnyIP로 설정하는 것이 속 편합니다.)

그런 다음, 화면에 나오는 텍스트에서 지시하는 것처럼, 원격 PC(또는 WSL) 측에서 "pydevd-pycharm~=212.4746.96" 구성 요소를 설치하고,

$ pip install pydevd-pycharm~=212.4746.96

원격 PC에서 실행할 스크립트에는 적절한 디버그 시점을 선택해 아래의 스크립트를 추가합니다. (즉, 아래의 경우는 시작하자마자 PyCharm IDE의 디버그 서버로 접속을 시도합니다.)

# main.py

import pydevd_pycharm
pydevd_pycharm.settrace('localhost', port=14444, stdoutToServer=True, stderrToServer=True)


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]


def get_wsgi_application():
    return simple_app


application = get_wsgi_application()

자, 이걸로 준비 작업은 끝입니다. 이제 PyCharm은 해당 Configuration의 설정으로 디버그를 시작하면 콘솔 화면에 "Waiting for process connection..."이라고 뜨며 연결을 대기합니다.

이후, WSL 측에서 파이썬 스크립트를 실행하면,

$ python main.py
Could not connect to localhost: 14444
Traceback (most recent call last):
  File "/home/testusr/.local/lib/python3.8/site-packages/_pydevd_bundle/pydevd_comm.py", line 507, in start_client
    s.connect((host, port))
ConnectionRefusedError: [Errno 111] Connection refused
Traceback (most recent call last):
  File "main.py", line 7, in <module>
    pydevd.settrace('localhost', port=14444, stdoutToServer=True, stderrToServer=True)
  File "/home/testusr/.local/lib/python3.8/site-packages/pydevd.py", line 2696, in settrace
    _locked_settrace(
  File "/home/testusr/.local/lib/python3.8/site-packages/pydevd.py", line 2777, in _locked_settrace
    py_db.connect(host, port)  # Note: connect can raise error.
  File "/home/testusr/.local/lib/python3.8/site-packages/pydevd.py", line 1353, in connect
    s = start_client(host, port)
  File "/home/testusr/.local/lib/python3.8/site-packages/_pydevd_bundle/pydevd_comm.py", line 507, in start_client
    s.connect((host, port))
ConnectionRefusedError: [Errno 111] Connection refused

(원격 호스트라면 오류 없이 잘 실행이 되었겠지만) 아쉽게도 WSL 환경이라 "Could not connect to localhost - ConnectionRefusedError: [Errno 111] Connection refused" 오류가 발생하는군요. ^^




이에 대한 원인은 WSL 2에서의 네트워크의 특징 때문입니다.

WSL 2의 네트워크 통신 방법
; https://www.sysnet.pe.kr/2/0/12347

즉, WSL 인스턴스 측에서 윈도우 호스트 측으로의 "localhost" 접속이 불가능하므로, PyCharm 측의 "IDE host name" 바인딩을 "localhost"가 아닌 "/etc/resolv.conf"에서 보이는 IP로,

$  cat /etc/resolv.conf
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver 172.23.208.1

대체해야 합니다. (혹은 그냥 위에서도 언급했지만 "0.0.0.0"으로 설정합니다.) 물론, 스크립트에서도 변경해주고,

pydevd_pycharm.settrace('172.23.208.1', port=14444, stdoutToServer=True, stderrToServer=True)

다시 실행하면 이번에는 정상적으로 디버깅 연결이 됩니다.




그런데, 디버깅 연결까지는 되었지만 아마도 화면에는 여전히 다음과 같은 식의 오류가 발생할 수 있습니다.

/mnt/d/workshop2/python-wsgi-app/main.py can't be found in project. You can continue debugging, but without the source. To fix that you can do one of the following:


소스 코드를 찾을 수 없다는 것인데, 어쩔 수 없습니다. "Run/Debug Configuration"에서 다음과 같이 매핑을 추가해야 합니다.

passive_remote_debug_2.png

이후 다시 디버깅 연결을 하면 콘솔에는 다음의 메시지와 함께,

Starting debug server at port 14,444
Use the following code to connect to the debugger:
import pydevd_pycharm
pydevd_pycharm.settrace('172.23.208.1', port=14444, stdoutToServer=True, stderrToServer=True)
Waiting for process connection…
Connected to pydev debugger (build 212.4746.96)

정상적으로 main.py가 열리고 pydevd.settrace 호출 다음 라인에서 실행이 멈춰 있는 것을 확인할 수 있습니다.

참고로 PyCharm IDE는 디버깅 서버를 한 번 열어 두면 계속 접속을 받아들이도록 동작합니다. 따라서, 클라이언트 측에서 프로세스를 종료해 연결이 끊겨도 PyCharm 측의 디버그 서버를 다시 실행할 필요 없이 그냥 클라이언트 측 프로세스만 다시 시작해 pydevd.settrace 호출을 하면 PyCharm 디버그 서버에 연결이 됩니다.




이로 인해 다음의 소스 코드를,

import pydevd
pydevd.settrace('172.23.208.1', port=14444, stdoutToServer=True, stderrToServer=True)

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]


def get_wsgi_application():
    return simple_app


application = get_wsgi_application()

이전에는 gunicorn으로 실행하는 경우,

$ gunicorn -b 0.0.0.0:18090 main

PyCharm에서 (F5 실행) 디버깅을 할 수 없었지만 이제는 pydevd.settrace의 호출로 인해 디버깅이 가능해졌습니다.

(그건 그렇고, 이건 Visual Studio에도 도입을 했으면... 하는 희망이 생기는군요. ^^)




참고로, 아래와 같이 코딩해도 되지만,

import pydevd_pycharm
pydevd_pycharm.settrace('172.23.208.1', port=14444, stdoutToServer=True, stderrToServer=True)

이렇게 해도 정상적으로 동작을 했습니다.

import pydevd
pydevd.settrace('172.23.208.1', port=14444, stdoutToServer=True, stderrToServer=True)

이에 대한 이력은 잘 모르겠지만 pydevd는 예전 모듈인 것 같고, 하위 호한으로 인해 남겨둔 듯합니다. (혹시 이에 대한 차이를 아시는 분은 덧글 부탁드립니다. ^^)




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







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

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

비밀번호

댓글 작성자
 




... 61  62  63  64  65  66  67  68  [69]  70  71  72  73  74  75  ...
NoWriterDateCnt.TitleFile(s)
12211정성태4/27/202019268개발 환경 구성: 486. WSL에서 Makefile로 공개된 리눅스 환경의 C/C++ 소스 코드 빌드
12210정성태4/20/202020712.NET Framework: 903. .NET Framework의 Strong-named 어셈블리 바인딩 (1) - app.config을 이용한 바인딩 리디렉션 [1]파일 다운로드1
12209정성태4/13/202017416오류 유형: 614. 리눅스 환경에서 C/C++ 프로그램이 Segmentation fault 에러가 발생한 경우 (2)
12208정성태4/12/202015982Linux: 29. 리눅스 환경에서 C/C++ 프로그램이 Segmentation fault 에러가 발생한 경우
12207정성태4/2/202015839스크립트: 19. Windows PowerShell의 NonInteractive 모드
12206정성태4/2/202018448오류 유형: 613. 파일 잠금이 바로 안 풀린다면? - The process cannot access the file '...' because it is being used by another process.
12205정성태4/2/202015111스크립트: 18. Powershell에서는 cmd.exe의 명령어를 지원하진 않습니다.
12204정성태4/1/202015112스크립트: 17. Powershell 명령어에 ';' (semi-colon) 문자가 포함된 경우
12203정성태3/18/202017958오류 유형: 612. warning: 'C:\ProgramData/Git/config' has a dubious owner: '...'.
12202정성태3/18/202021210개발 환경 구성: 486. .NET Framework 프로젝트를 위한 GitLab CI/CD Runner 구성
12201정성태3/18/202018441오류 유형: 611. git-credential-manager.exe: Using credentials for username "Personal Access Token". [1]
12200정성태3/18/202018532VS.NET IDE: 145. NuGet + Github 라이브러리 디버깅 관련 옵션 3가지 - "Enable Just My Code" / "Enable Source Link support" / "Suppress JIT optimization on module load (Managed only)"
12199정성태3/17/202016179오류 유형: 610. C# - CodeDomProvider 사용 시 Unhandled Exception: System.IO.DirectoryNotFoundException: Could not find a part of the path '...\f2_6uod0.tmp'.
12198정성태3/17/202019533오류 유형: 609. SQL 서버 접속 시 "Cannot open user default database. Login failed."
12197정성태3/17/202018830VS.NET IDE: 144. .NET Core 콘솔 응용 프로그램을 배포(publish) 시 docker image 자동 생성 - 두 번째 이야기 [1]
12196정성태3/17/202015950오류 유형: 608. The ServicedComponent being invoked is not correctly configured (Use regsvcs to re-register).
12195정성태3/16/202018269.NET Framework: 902. C# - 프로세스의 모든 핸들을 열람 - 세 번째 이야기
12194정성태3/16/202021000오류 유형: 607. PostgreSQL - Npgsql.NpgsqlException: sorry, too many clients already
12193정성태3/16/202017923개발 환경 구성: 485. docker - SAP Adaptive Server Enterprise 컨테이너 실행 [1]
12192정성태3/14/202019947개발 환경 구성: 484. docker - Sybase Anywhere 16 컨테이너 실행
12191정성태3/14/202021054개발 환경 구성: 483. docker - OracleXE 컨테이너 실행 [1]
12190정성태3/14/202015635오류 유형: 606. Docker Desktop 업그레이드 시 "The process cannot access the file 'C:\Program Files\Docker\Docker\resources\dockerd.exe' because it is being used by another process."
12189정성태3/13/202021238개발 환경 구성: 482. Facebook OAuth 처리 시 상태 정보 전달 방법과 "유효한 OAuth 리디렉션 URI" 설정 규칙
12188정성태3/13/202026025Windows: 169. 부팅 시점에 실행되는 chkdsk 결과를 확인하는 방법
12187정성태3/12/202015605오류 유형: 605. NtpClient was unable to set a manual peer to use as a time source because of duplicate error on '...'.
12186정성태3/12/202017404오류 유형: 604. The SysVol Permissions for one or more GPOs on this domain controller and not in sync with the permissions for the GPOs on the Baseline domain controller.
... 61  62  63  64  65  66  67  68  [69]  70  71  72  73  74  75  ...