다음을 통해 공유


Visual Studio에서 Python 및 C++를 함께 디버그

대부분의 일반 Python 디버거는 Python 코드 디버깅만 지원하지만 개발자는 C 또는 C++에서 Python을 사용하는 것이 일반적입니다. 혼합 코드를 사용하는 일부 시나리오는 고성능이 필요한 애플리케이션이거나 플랫폼 API를 직접 호출하는 기능이 Python 및 C 또는 C++로 코딩되는 경우가 많습니다.

Visual Studio는 Python 및 네이티브 C/C++ 코드에 대한 통합된 동시 혼합 모드 디버깅을 제공합니다. 지원은 Visual Studio 설치 관리자에서 Python 개발 워크로드에 대한 Python 네이티브 개발 도구 옵션을 선택할 때 사용할 수 있습니다.

Visual Studio 설치 관리자에서 선택한 Python 네이티브 개발 도구 옵션을 보여 주는 스크린샷

이 문서에서는 다음과 같은 혼합 모드 디버깅 기능을 사용하는 방법을 알아봅니다.

  • 결합된 호출 스택
  • Python과 네이티브 코드 간 단계
  • 두 코드 형식의 중단점
  • 파이썬 객체의 네이티브 프레임 내 표현 보기 및 네이티브 객체를 파이썬 표현으로 변환하기
  • Python 프로젝트 또는 C++ 프로젝트의 컨텍스트 내에서 디버깅

Visual Studio에서 Python 및 C++ 코드에 대한 혼합 모드 디버깅의 예를 보여 주는 스크린샷

필수 조건

  • Visual Studio 2017 이상. 혼합 모드 디버깅은 Visual Studio 2015 이하의 Visual Studio 1.x용 Python 도구에서 사용할 수 없습니다.

  • Python 워크로드를 지원하는 Visual Studio가 설치되었습니다. 자세한 내용은 Visual Studio에서 Python 지원 설치를 참조하세요.

Python 프로젝트에서 혼합 모드 디버깅 사용

다음 단계에서는 Python 프로젝트에서 혼합 모드 디버깅을 사용하도록 설정하는 방법을 설명합니다.

  1. 솔루션 탐색기에서 Python 프로젝트를 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다.

  2. 속성 창에서 디버그 탭을 선택한 다음, 네이티브 코드 디버깅 사용> 옵션을 선택합니다.

    Visual Studio에서 네이티브 코드 디버깅 사용 속성을 설정하는 방법을 보여 주는 스크린샷

    이 옵션은 모든 디버깅 세션에 대해 혼합 모드를 사용하도록 설정합니다.

    팁 (조언)

    네이티브 코드 디버깅을 사용하도록 설정하면 프로그램이 완료된 직후에 Python 출력 창이 닫히고 아무 키나 눌러 프롬프트 를 계속 표시하지 않고 종료될 수 있습니다. 네이티브 코드 디버깅을 사용하도록 설정한 후 일시 중지 및 프롬프트를 강제로 적용하려면 -i 탭의 인터프리터 인수> 필드에 인수를 추가 합니다. 이 인수는 코드가 실행된 후 Python 인터프리터를 대화형 모드로 전환합니다. 프로그램에서 Ctrl ++선택하여 창을 닫을 때까지 기다립니다.

  3. 파일>저장(또는 Ctrl+S)을 선택하여 속성 변경 내용을 저장합니다.

  4. 혼합 모드 디버거를 기존 프로세스에 연결하려면 프로세스에 연결 디버그> 선택합니다. 대화 상자가 열립니다.

    1. 프로세스에 연결 대화 상자의 목록에서 적절한 프로세스를 선택합니다.

    2. [연결] 필드의 경우 [선택] 옵션을 사용하여 [코드 형식 선택] 대화 상자를 엽니다.

    3. 코드 형식 선택 대화 상자에서 이러한 코드 형식 디버그 옵션을 선택합니다.

    4. 목록에서 Python(네이티브) 확인란을 선택하고 확인을 선택합니다.

      Visual Studio에서 디버깅을 위해 Python(네이티브) 코드 형식을 선택하는 방법을 보여 주는 스크린샷

    5. 연결을 선택하여 디버거를 시작합니다.

    코드 형식 설정은 영구적입니다. 혼합 모드 디버깅을 사용하지 않도록 설정하고 나중에 다른 프로세스에 연결하려면 Python(네이티브) 코드 형식 확인란의 선택을 취소하고 네이티브 코드 형식 확인란을 선택합니다.

    네이티브 옵션 외에 또는 그 대신 다른 코드 형식을 선택할 수 있습니다. 예를 들어 관리되는 애플리케이션이 CPython을 호스트하고 네이티브 확장 모듈을 사용하고 세 코드 프로젝트를 모두 디버그하려는 경우 Python, 네이티브관리 확인란을 선택합니다. 이 방법을 사용하면 결합된 호출 스택과 세 런타임 간의 단계별 실행을 비롯한 통합 디버깅 환경을 제공합니다.

가상 환경 작업

이 혼합 모드 디버깅 방법을 사용하여 가상 환경(venvs)을 사용하는 경우 Windows용 Python은 Visual Studio에서 하위 프로세스로 찾아서 로드하는 venvs용 스텁 파일을 사용합니다 python.exe .

  • Python 3.8 이상에서는 혼합 모드에서 다중 프로세스 디버깅을 지원하지 않습니다. 디버깅 세션을 시작하면 스텁 하위 프로세서가 애플리케이션이 아닌 디버그됩니다. 연결 시나리오의 경우 해결 방법은 올바른 python.exe 파일에 연결하는 것입니다. 디버깅을 사용하여 애플리케이션을 시작할 때(예: F5 바로 가기 키를 통해) 명령을 C:\Python310-64\python.exe -m venv venv --symlinks사용하여 venv를 만들 수 있습니다. 명령에서 기본 설정 버전의 Python을 삽입합니다. 기본적으로 관리자만 Windows에서 symlink를 만들 수 있습니다.

  • 3.8 이전 Python 버전의 경우 혼합 모드 디버깅은 venvs에서 예상대로 작동해야 합니다.

전역 환경에서 실행해도 Python 버전에서 이러한 문제가 발생하지는 않습니다.

Python 기호 설치

처음으로 혼합 모드에서 디버깅을 시작하면 Python 기호 필수 대화 상자가 표시될 수 있습니다. 지정된 Python 환경에 대해 기호를 한 번만 설치해야 합니다. Visual Studio 설치 관리자(Visual Studio 2017 이상)를 통해 Python 지원을 설치하면 기호가 자동으로 포함됩니다. 자세한 내용은 Visual Studio에서 Python 인터프리터용 디버깅 기호 설치를 참조하세요.

Python 소스 코드 액세스

디버깅할 때 표준 Python 자체의 소스 코드를 사용할 수 있도록 할 수 있습니다.

  1. https://www.python.org/downloads/source/로 이동합니다.

  2. 버전에 적합한 Python 소스 코드 보관 파일을 다운로드하고 폴더에 코드를 추출합니다.

  3. Visual Studio에서 Python 소스 코드의 위치를 묻는 메시지가 표시되면 추출 폴더의 특정 파일을 가리킵니다.

C/C++ 프로젝트에서 혼합 모드 디버깅 사용

Visual Studio 2017 버전 15.5 이상에서는 C/C++ 프로젝트에서 혼합 모드 디버깅을 지원합니다. 이 사용의 예는 python.org 설명된 대로 다른 애플리케이션에 Python을 포함하려는 경우입니다.

다음 단계에서는 C/C++ 프로젝트에 대해 혼합 모드 디버깅을 사용하도록 설정하는 방법을 설명합니다.

  1. 솔루션 탐색기에서 C/C++ 프로젝트를 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다.

  2. 속성 페이지 창에서 구성 속성>디버깅 탭을 선택합니다.

  3. 디버거에 대한 드롭다운 메뉴를 확장 하여 옵션을 시작하고Python/네이티브 디버깅을 선택합니다.

    Visual Studio에서 C/C++ 프로젝트에 대한 Python 네이티브 디버깅 옵션을 선택하는 방법을 보여 주는 스크린샷

    비고

    Python/네이티브 디버깅 옵션이 표시되지 않으면 먼저 Visual Studio 설치 관리자를 사용하여 Python 네이티브 개발 도구를 설치해야 합니다. 네이티브 디버깅 옵션은 Python 개발 워크로드에서 사용할 수 있습니다. 자세한 내용은 Visual Studio에서 Python 지원 설치를 참조하세요.

  4. 확인을 선택하여 변경 내용을 저장합니다.

프로그램 런처 디버그

이 메서드를 사용하는 경우, 하위 py.exe 프로세스를 생성하므로 프로그램 실행기를 디버그할 수 없습니다. 디버거는 하위 프로세스에 연결되지 않습니다. 이 시나리오에서 해결 방법은 다음과 같이 인수를 python.exe 사용하여 프로그램을 직접 시작하는 것입니다.

  1. C/C++ 프로젝트의 속성 페이지 창에서 구성 속성>디버깅 탭으로 이동합니다.

  2. 명령 옵션의 경우 프로그램 파일의 전체 경로를 python.exe 지정합니다.

  3. 명령 인수 필드에 원하는 인수 를 지정합니다.

혼합 모드 디버거를 연결합니다

Visual Studio 2017 버전 15.4 이하의 경우 Visual Studio에서 Python 프로젝트를 시작할 때만 직접 혼합 모드 디버깅을 사용할 수 있습니다. C/C++ 프로젝트는 네이티브 디버거만 사용하므로 지원이 제한됩니다.

이 시나리오의 경우 해결 방법은 디버거를 별도로 연결하는 것입니다.

  1. 디버깅하지 않고 디버그> 시작을 선택하여 디버깅하지 않고 C++ 프로젝트를 시작하거나 바로 가기 키 Ctrl+F5를 사용합니다.

  2. 혼합 모드 디버거를 기존 프로세스에 연결하려면 프로세스에 연결 디버그> 선택합니다. 대화 상자가 열립니다.

    1. 프로세스에 연결 대화 상자의 목록에서 적절한 프로세스를 선택합니다.

    2. [연결] 필드의 경우 [선택] 옵션을 사용하여 [코드 형식 선택] 대화 상자를 엽니다.

    3. 코드 형식 선택 대화 상자에서 이러한 코드 형식 디버그 옵션을 선택합니다.

    4. 목록에서 Python 확인란을 선택하고 확인을 선택합니다.

    5. 첨부를 선택하여 디버거를 시작합니다.

팁 (조언)

디버거를 연결하기 전에 디버그하려는 Python 코드를 호출하지 않도록 C++ 애플리케이션에서 일시 중지 또는 지연을 추가할 수 있습니다.

혼합 모드 관련 기능 살펴보기

Visual Studio는 애플리케이션을 더 쉽게 디버그할 수 있도록 몇 가지 혼합 모드 디버깅 기능을 제공합니다.

결합된 호출 스택 사용

호출 스택 창에는 네이티브 및 Python 스택 프레임이 인터리브되어 있으며, 두 프레임 사이에 전환이 표시됩니다.

Visual Studio에서 혼합 모드 디버깅이 있는 결합된 호출 스택 창의 스크린샷

  • 전환 방향을 지정하지 않고 전환을 [외부 코드] 로 표시하려면 도구>옵션 창을 사용합니다. 모든 설정>디버깅> 섹션을 확장하고 내 코드만 사용 확인란을 선택합니다.
  • 전환 방향을 지정하지 않고 전환을 [외부 코드] 로 표시하려면 [도구>옵션 ] 대화 상자를 사용합니다. 디버깅> 섹션을 확장하고 내 코드만 사용 확인란을 선택한 다음 확인을 선택합니다.
  • 호출 프레임을 활성화하려면 프레임을 두 번 클릭합니다. 이 작업은 가능한 경우 해당 소스 코드도 엽니다. 소스 코드를 사용할 수 없는 경우 프레임이 여전히 활성화되고 지역 변수를 검사할 수 있습니다.

Python과 네이티브 코드 간 단계

Visual Studio는 혼합 모드 디버거 코드 형식 간의 변경 내용을 올바르게 처리할 수 있도록 F11(Step Into) 또는 Step Out(Shift+F11) 명령을 제공합니다.

  • Python이 C에서 구현된 형식의 메서드를 호출할 때, 해당 메서드 호출을 추적하면 메서드를 구현하는 함수의 시작 부분에서 중지됩니다.

  • 이 동일한 동작은 네이티브 코드가 Python 코드를 호출하는 Python API 함수를 호출할 때 발생합니다. Python에서 원래 정의된 함수 값에 대해 PyObject_CallObject 호출로 단계별 진입하면 Python 함수의 시작 부분에서 중단됩니다.

  • Python에서 네이티브로의 단계별 실행은 ctypes를 통해 Python에서 호출되는 네이티브 함수에도 지원됩니다.

네이티브 코드에서 PyObject 값 보기 사용

네이티브(C 또는 C++) 프레임이 활성화되면 해당 지역 변수가 디버거 로컬 창에 표시됩니다. 네이티브 Python 확장 모듈에서 이러한 변수의 대부분은 형식 PyObject (typedef의 경우 _object) 또는 몇 가지 다른 기본 Python 형식입니다. 혼합 모드 디버깅에서 이러한 값은 [Python 보기]라는 레이블이 지정된 다른 자식 노드를 표시합니다.

  • 변수의 Python 표현을 보려면 노드를 확장합니다. 변수 보기는 동일한 개체를 참조하는 지역 변수가 Python 프레임에 있는지 확인하는 것과 동일합니다. 이 노드의 자식은 편집할 수 있습니다.

    Visual Studio의 로컬 창에 있는 Python 보기를 보여 주는 스크린샷

  • 이 기능을 사용하지 않도록 설정하려면 로컬 창의 아무 곳이나 마우스 오른쪽 단추로 클릭하고 Python>표시 Python 노드 보기 메뉴 옵션을 전환합니다.

    로컬 창에 Python 보기 노드 표시 옵션을 사용하도록 설정하는 방법을 보여 주는 스크린샷

Python 뷰 노드를 표시하는 C 형식

다음 C 형식은 사용하도록 설정된 경우 [Python 보기] 노드를 보여 줍니다.

  • PyObject
  • PyVarObject
  • PyTypeObject
  • PyByteArrayObject
  • PyBytesObject
  • PyTupleObject
  • PyListObject
  • PyDictObject
  • PySetObject
  • PyIntObject
  • PyLongObject
  • PyFloatObject
  • PyStringObject
  • PyUnicodeObject

직접 작성하는 형식에는 [Python 보기]가 자동으로 표시되지 않습니다. Python 3.x용 확장을 작성할 때 이 부족은 일반적으로 문제가 되지 않습니다. 모든 개체에는 ob_base 궁극적으로 나열된 C 형식 중 하나의 필드가 있으므로 [Python 보기] 가 나타납니다.

Python 코드에서 네이티브 값 보기

Python 프레임이 활성화된 경우 로컬 창에서 네이티브 값에 [C++ 보기]를 사용하도록 설정할 수 있습니다. 이 기능은 기본적으로 사용되지 않습니다.

  • 이 기능을 사용하도록 설정하려면 로컬 창을 마우스 오른쪽 단추로 클릭하고 Python>C++ 노드 보기 메뉴 옵션을 설정합니다.

    로컬 창에 대해 C++ 노드 보기 옵션을 사용하도록 설정하는 방법을 보여 주는 스크린샷

  • [C++ 뷰] 노드는 네이티브 프레임에 표시되는 것과 동일한 값에 대한 기본 C/C++ 구조체의 표현을 제공합니다. Python long 정수형에 대한 _longobject (typedef인 PyLongObject의) 인스턴스를 표시하고, 직접 만든 네이티브 클래스에 대한 형식을 유추하려고 합니다. 이 노드의 자식은 편집할 수 있습니다.

    Visual Studio의 로컬 창에 있는 C++ 보기를 보여 주는 스크린샷

개체의 자식 필드가 형식 PyObject이거나 지원되는 다른 형식인 경우 [Python 뷰] 표현 노드가 있습니다(해당 표현을 사용하는 경우). 이 동작을 사용하면 링크가 Python에 직접 노출되지 않는 개체 그래프를 탐색할 수 있습니다.

Python 개체 메타데이터를 사용하여 개체 형식을 결정하는 [Python 뷰] 노드와 달리 [C++ 뷰]에도 이와 유사한 신뢰할 수 있는 메커니즘이 없습니다. 일반적으로 Python 값(즉, PyObject 참조)을 고려할 때 어떤 C/C++ 구조체를 지원하는지 안정적으로 확인할 수 없습니다. 혼합 모드 디버거는 개체의 다양한 필드(예: PyTypeObject의 필드가 참조하는 ob_type) 중 함수 포인터 유형이 있는 필드를 확인하여 형식을 추측하려고 합니다. 이러한 함수 포인터 중 하나가 확인할 수 있는 함수를 참조하고 해당 함수 self 에 보다 PyObject*구체적인 형식의 매개 변수가 있는 경우 해당 형식은 백업 형식으로 간주됩니다.

다음 예제 ob_type->tp_init 에서는 지정된 개체의 값이 다음 함수를 가리킵니다.

static int FobObject_init(FobObject* self, PyObject* args, PyObject* kwds) {
    return 0;
}

이 경우 디버거는 개체 FobObject의 C 형식이 올바른지 추론할 수 있습니다. 디버거가 보다 정확한 형식 tp_init을 확인할 수 없는 경우 다른 필드로 이동합니다. 이러한 필드 중 하나에서 형식을 추론할 수 없는 경우 [C++ 뷰] 노드는 개체를 인스턴스로 PyObject 표시합니다.

사용자 지정 작성 형식에 항상 유용한 표현을 얻으려면 형식을 등록할 때 하나 이상의 특수 함수를 등록하고 강력한 형식 self 의 매개 변수를 사용하는 것이 가장 좋습니다. 대부분의 형식은 해당 요구 사항을 자연스럽게 충족합니다. 다른 유형의 경우, tp_init 검사는 일반적으로 이 용도로 사용하기에 가장 편리한 진입점입니다. 디버거 형식 유추를 사용하도록 설정하기 위해서만 존재하는 형식에 대한 더미 구현 tp_init 은 앞의 예제와 같이 즉시 0을 반환할 수 있습니다.

표준 Python 디버깅의 차이점 검토

혼합 모드 디버거는 표준 Python 디버거와 다릅니다. 몇 가지 추가 기능을 도입하지만 다음과 같이 일부 Python 관련 기능이 부족합니다.

  • 지원되지 않는 기능에는 조건부 중단점, 대화형 디버그 창 및 플랫폼 간 원격 디버깅이 포함됩니다.
  • 직접 실행 창은 사용할 수 있지만 이 섹션에 나열된 모든 제한 사항을 포함하여 기능의 하위 집합이 제한되어 있습니다.
  • 지원되는 Python 버전에는 CPython 2.7 및 3.3 이상만 포함됩니다.
  • Visual Studio Shell에서 Python을 사용하려면(예: 통합 설치 관리자와 함께 설치하는 경우) Visual Studio에서 C++ 프로젝트를 열 수 없습니다. 따라서 C++ 파일에 대한 편집 환경은 기본 텍스트 편집기 전용입니다. 그러나 C/C++ 디버깅 및 혼합 모드 디버깅은 소스 코드, 네이티브 코드로 단계별 실행 및 디버거 창에서 C++ 식 평가를 사용하여 Shell에서 완전히 지원됩니다.
  • 로컬조사식 디버거 도구 창에서 Python 개체를 볼 때 혼합 모드 디버거는 개체의 구조만 표시합니다. 속성을 자동으로 평가하거나 계산된 특성을 표시하지 않습니다. 컬렉션의 경우 기본 제공 컬렉션 형식(tuple, , listdict,set)에 대한 요소만 표시합니다. 사용자 지정 컬렉션 형식은 일부 기본 제공 컬렉션 형식에서 상속되지 않는 한 컬렉션으로 시각화되지 않습니다.
  • 식 평가는 다음 섹션에 설명된 대로 처리됩니다.

표현식 평가 사용

표준 Python 디버거를 사용하면 I/O 작업 또는 기타 유사한 시스템 호출에서 차단되지 않는 한, 디버그된 프로세스가 코드 실행을 중단한 어떤 지점에서라도 WatchImmediate 창에서 임의의 Python 표현식을 평가할 수 있습니다. 혼합 모드 디버깅에서 임의 식은 Python 코드에서 중지된 경우, 중단점 이후 또는 코드를 한 단계 더 실행할 때만 평가할 수 있습니다. 중단점 또는 단계별 작업이 발생한 스레드에서만 식을 평가할 수 있습니다.

디버거가 네이티브 코드에서 중지되거나 단계별 작업 후 또는 다른 스레드와 같이 설명된 조건이 적용되지 않는 Python 코드에서 중지되는 경우). 식 평가는 현재 선택한 프레임 범위에서 로컬 및 전역 변수에 액세스하고, 해당 필드에 액세스하고, 리터럴을 사용하여 기본 제공 컬렉션 형식을 인덱싱하는 것으로 제한됩니다. 예를 들어 모든 식별자가 적절한 형식의 기존 변수 및 필드를 참조하는 경우 모든 컨텍스트에서 다음 식을 평가할 수 있습니다.

foo.bar[0].baz['key']

혼합 모드 디버거도 이러한 식을 다르게 확인합니다. 모든 멤버 액세스 작업은 개체에서 직접적으로 포함된 필드(__dict__ 또는 __slots__의 항목, 또는 tp_members를 통해 Python에 노출된 네이티브 구조체의 필드)만 조회하며, __getattr__, __getattribute__ 및 설명자 논리를 무시합니다. 마찬가지로 모든 인덱싱 작업은 무시하고 __getitem__컬렉션의 내부 데이터 구조에 직접 액세스합니다.

일관성을 위해 이 이름 확인 체계는 제한된 식 평가에 대한 제약 조건과 일치하는 모든 식에 사용됩니다. 이 체계는 현재 중지점에서 임의 식이 허용되는지 여부에 관계없이 적용됩니다. 완전한 기능을 갖춘 계산기를 사용할 수 있을 때 적절한 Python 의미 체계를 강제 적용하려면 식을 괄호로 묶습니다.

(foo.bar[0].baz['key'])