Společné ladění Pythonu a C++ v sadě Visual Studio

Většina běžných ladicích programů Pythonu podporuje pouze ladění kódu Pythonu, ale pro vývojáře je běžné používat Python s jazykem C nebo C++. Některé scénáře, které používají smíšený kód, jsou aplikace, které vyžadují vysoký výkon nebo schopnost přímo vyvolat rozhraní API platformy, jsou často kódovány v Pythonu a C nebo C++.

Visual Studio poskytuje integrované souběžné ladění ve smíšeném režimu pro python a nativní kód jazyka C/C++. Podpora je dostupná, když v instalačním programu sady Visual Studio vyberete možnost nativních vývojových nástrojů Pythonu pro úlohu Vývoj pro Python:

Snímek obrazovky znázorňující možnost nativních vývojových nástrojů Pythonu vybranou v Instalační program pro Visual Studio

V tomto článku se dozvíte, jak pracovat s následujícími funkcemi ladění ve smíšeném režimu:

  • Kombinované zásobníky volání
  • Krok mezi Pythonem a nativním kódem
  • Zarážky v obou typech kódu
  • Zobrazení reprezentací objektů v nativních rámcích a naopak
  • Ladění v kontextu projektu Pythonu nebo projektu C++

Snímek obrazovky znázorňující příklad ladění ve smíšeném režimu pro kód Pythonu a C++ v sadě Visual Studio

Požadavky

  • Visual Studio 2017 a novější Ladění ve smíšeném režimu není dostupné v nástrojích Python Tools for Visual Studio 1.x v sadě Visual Studio 2015 a starších verzích.

  • Visual Studio nainstalované s podporou úloh Pythonu Další informace najdete v tématu Instalace podpory Pythonu v sadě Visual Studio.

Povolení ladění ve smíšeném režimu v projektu Pythonu

Následující kroky popisují, jak povolit ladění ve smíšeném režimu v projektu Pythonu:

  1. V Průzkumník řešení klikněte pravým tlačítkem na projekt Pythonu a vyberte Vlastnosti.

  2. V podokně Vlastnosti vyberte kartu Ladění a pak vyberte možnost Ladění>povolit nativní ladění kódu:

    Snímek obrazovky, který ukazuje, jak nastavit vlastnost Povolit ladění nativního kódu v sadě Visual Studio

    Tato možnost umožňuje smíšený režim pro všechny relace ladění.

    Tip

    Když povolíte ladění nativního kódu, okno výstupu Pythonu se může zavřít hned po dokončení programu bez pozastavení a zobrazení výzvy stisknutím libovolné klávesy . Chcete-li vynutit pozastavení a výzvu po povolení ladění nativního kódu, přidejte -i argument do pole Spustit>argumenty interpretu na kartě Ladění. Tento argument umístí interpret Pythonu do interaktivního režimu po spuštění kódu. Program čeká, až vyberete Ctrl+Z+Enter a zavřete okno.

  3. Výběrem možnosti Uložit soubor>(nebo Ctrl+S) uložte změny vlastnosti.

  4. Pokud chcete k existujícímu procesu připojit ladicí program ve smíšeném režimu, vyberte Připojit k procesu ladění>. Otevře se dialogové okno.

    1. V dialogovém okně Připojit k procesu vyberte v seznamu příslušný proces.

    2. Pro pole Připojit k pomocí možnosti Vybrat otevřete dialogové okno Vybrat typ kódu.

    3. V dialogovém okně Vybrat typ kódu zvolte možnost Ladit tyto typy kódu.

    4. V seznamu zaškrtněte políčko Python (nativní) a vyberte OK:

      Snímek obrazovky, který ukazuje, jak vybrat typ kódu Pythonu (nativní) pro ladění v sadě Visual Studio

    5. Chcete-li spustit ladicí program, vyberte Připojit .

    Nastavení typu kódu je trvalé. Pokud chcete později zakázat ladění ve smíšeném režimu a připojit se k jinému procesu, zrušte zaškrtnutí políčka Typ kódu Pythonu (nativní) a zaškrtněte políčko Typ nativního kódu.

    Kromě možnosti Native (Nativní) můžete vybrat i jiné typy kódu. Pokud například spravovaná aplikace hostuje CPython, který zase používá nativní rozšiřující moduly a chcete ladit všechny tři projekty kódu, zaškrtněte políčka Python, Native a Managed . Tento přístup poskytuje jednotné prostředí ladění, včetně kombinovaných zásobníků volání a krokování mezi všemi třemi moduly runtime.

Práce s virtuálními prostředími

Při použití této metody ladění ve smíšeném režimu pro virtuální prostředí (venvs), Python pro Windows používá python.exe soubor zástupných procedur pro venvs, které Sada Visual Studio najde a načte jako podproces.

  • V případě Pythonu 3.8 a novějšího nepodporuje smíšený režim ladění s více procesy. Při spuštění ladicí relace se dílčí proces zástupných procedur ladí místo aplikace. V případě scénářů připojení je alternativním řešením připojit se ke správnému python.exe souboru. Při spuštění aplikace s laděním (například pomocí klávesové zkratky F5 ) můžete vytvořit venv pomocí příkazu C:\Python310-64\python.exe -m venv venv --symlinks. V příkazu vložte upřednostňovanou verzi Pythonu. Ve výchozím nastavení můžou symlinky ve Windows vytvářet jenom správci.

  • U verzí Pythonu starších než 3.8 by ladění smíšeného režimu mělo fungovat podle očekávání s venvs.

Spuštění v globálním prostředí nezpůsobuje tyto problémy pro žádnou verzi Pythonu.

Instalace symbolů Pythonu

Při prvním spuštění ladění ve smíšeném režimu se může zobrazit dialogové okno Povinné symboly Pythonu. Symboly je potřeba nainstalovat jenom jednou pro libovolné prostředí Pythonu. Symboly se automaticky zahrnou, pokud nainstalujete podporu Pythonu prostřednictvím Instalační program pro Visual Studio (Visual Studio 2017 a novější). Další informace najdete v tématu Instalace symbolů ladění pro interprety Pythonu v sadě Visual Studio.

Přístup ke zdrojovému kódu Pythonu

Zdrojový kód pro samotný standardní Python můžete zpřístupnit při ladění.

  1. Přejděte na https://www.python.org/downloads/source/.

  2. Stáhněte si archiv zdrojového kódu Pythonu odpovídající vaší verzi a extrahujte kód do složky.

  3. Když visual Studio vyzve k zadání umístění zdrojového kódu Pythonu, přejděte na konkrétní soubory ve složce pro extrakci.

Povolení ladění ve smíšeném režimu v projektu C/C++

Visual Studio 2017 verze 15.5 a novější podporuje ladění ve smíšeném režimu z projektu C/C++. Příkladem tohoto použití je, když chcete vložit Python do jiné aplikace, jak je popsáno v python.org.

Následující kroky popisují, jak povolit ladění ve smíšeném režimu pro projekt C/C++:

  1. V Průzkumník řešení klikněte pravým tlačítkem myši na projekt C/C++ a vyberte Vlastnosti.

  2. V podokně Stránky vlastností vyberte kartu Ladění vlastností>konfigurace.

  3. Rozbalte rozevírací nabídku pro ladicí program, aby se spustila možnost, a vyberte Python nebo Nativní ladění.

    Snímek obrazovky znázorňující výběr možnosti nativního ladění Pythonu pro projekt C/C++ v sadě Visual Studio

    Poznámka:

    Pokud možnost Ladění v Pythonu nebo nativním ladění nevidíte, musíte nejprve nainstalovat nativní vývojové nástroje Pythonu pomocí Instalační program pro Visual Studio. Možnost nativního ladění je k dispozici v rámci vývojové úlohy Pythonu. Další informace najdete v tématu Instalace podpory Pythonu v sadě Visual Studio.

  4. Kliknutím na TLAČÍTKO OK uložte změny.

Ladění spouštěče programů

Při použití této metody nelze ladit py.exe spouštěč programů, protože vytváří podřízený python.exe podproces. Ladicí program se nepřipojte k podprocesu. V tomto scénáři je alternativním řešením spustit python.exe program přímo s argumenty následujícím způsobem:

  1. V podokně Stránky vlastností projektu C/C++ přejděte na kartu Ladění vlastností> konfigurace.

  2. Pro možnost Příkaz zadejte úplnou cestu k python.exe souboru programu.

  3. Do pole Argumenty příkazu zadejte požadované argumenty.

Připojení ladicího programu ve smíšeném režimu

Pro Visual Studio 2017 verze 15.4 a starší je přímé ladění smíšeného režimu povoleno pouze při spuštění projektu Pythonu v sadě Visual Studio. Podpora je omezená, protože projekty C/C++ používají pouze nativní ladicí program.

V tomto scénáři je alternativním řešením připojit ladicí program samostatně:

  1. Spusťte projekt C++ bez ladění tak>, že vyberete Spustit ladění bez ladění nebo použijete klávesovou zkratku Ctrl+F5.

  2. Pokud chcete k existujícímu procesu připojit ladicí program ve smíšeném režimu, vyberte Připojit k procesu ladění>. Otevře se dialogové okno.

    1. V dialogovém okně Připojit k procesu vyberte v seznamu příslušný proces.

    2. Pro pole Připojit k pomocí možnosti Vybrat otevřete dialogové okno Vybrat typ kódu.

    3. V dialogovém okně Vybrat typ kódu zvolte možnost Ladit tyto typy kódu.

    4. V seznamu zaškrtněte políčko Python a vyberte OK.

    5. Chcete-li spustit ladicí program, vyberte Připojit .

Tip

Do aplikace C++ můžete přidat pozastavení nebo zpoždění, abyste se ujistili, že před připojením ladicího programu nevolá kód Pythonu, který chcete ladit.

Prozkoumání funkcí specifických pro smíšený režim

Visual Studio nabízí několik funkcí ladění ve smíšeném režimu, které usnadňují ladění aplikace:

Použití kombinovaného zásobníku volání

V okně Zásobník volání se zobrazují nativní rámce zásobníku Pythonu prokládání s přechody označenými mezi těmito dvěma:

Snímek obrazovky okna kombinovaného zásobníku volání s laděním ve smíšeném režimu v sadě Visual Studio

  • Pokud chcete, aby se přechody zobrazovaly jako [externí kód] bez zadání směru přechodu, nastavte možnost Možnosti>>nástroje>Ladění obecné>povolit pouze můj kód.

  • Pokud chcete aktivovat libovolný rámec volání, poklikejte na rámec. Tato akce také otevře odpovídající zdrojový kód, pokud je to možné. Pokud zdrojový kód není dostupný, je rámec stále aktivní a je možné zkontrolovat místní proměnné.

Krok mezi Pythonem a nativním kódem

Visual Studio poskytuje příkazy Step Into (F11) nebo Step Out (Shift+F11), které umožňují ladicím programu smíšeného režimu správně zpracovávat změny mezi typy kódu.

  • Když Python volá metodu typu implementovaného v jazyce C, krokování volání této metody se zastaví na začátku nativní funkce, která implementuje metodu.

  • K tomuto chování dochází, když nativní kód volá funkci rozhraní PYTHON API, která má za následek vyvolání kódu Pythonu. Krokování volání PyObject_CallObject hodnoty funkce původně definované v Pythonu se zastaví na začátku funkce Pythonu.

  • Krokování z Pythonu na nativní je také podporováno pro nativní funkce vyvolané z Pythonu prostřednictvím typů ctype.

Použití zobrazení hodnot PyObject v nativním kódu

Pokud je aktivní nativní rámec (C nebo C++), místní proměnné se zobrazí v okně Locals ladicího programu. V nativních rozšiřujících modulech Pythonu je mnoho z těchto proměnných typu PyObject (což je typedef pro _object) nebo několik dalších základních typů Pythonu. V ladění ve smíšeném režimu tyto hodnoty představují další podřízený uzel označený jako [zobrazení Pythonu].

  • Pokud chcete zobrazit reprezentaci Pythonu proměnné, rozbalte uzel. Zobrazení proměnných je stejné jako v případě, že se v rámci Pythonu nachází místní proměnná odkazující na stejný objekt. Podřízené položky tohoto uzlu se dají upravovat.

    Snímek obrazovky znázorňující zobrazení Pythonu v okně Místní hodnoty v sadě Visual Studio

  • Pokud chcete tuto funkci zakázat, klikněte pravým tlačítkem na libovolné místo v okně Místní hodnoty a přepněte možnost nabídky Zobrazit uzly zobrazení Pythonu>:

    Snímek obrazovky, který ukazuje, jak povolit možnost Zobrazit uzly zobrazení Pythonu pro okno Místní hodnoty

Typy jazyka C, které zobrazují uzly zobrazení Pythonu

Následující typy jazyka C zobrazují uzly [zobrazení Pythonu], pokud jsou povolené:

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

[Zobrazení Pythonu] automaticky se nezobrazuje u typů, které sami vytvoříte. Když vytvoříte rozšíření pro Python 3.x, obvykle to není problém. Každý objekt má ob_base nakonec pole jednoho z uvedených typů jazyka C, což způsobí, že se zobrazí [zobrazení Pythonu].

Zobrazení nativních hodnot v kódu Pythonu

Pokud je aktivní rámeček Pythonu, můžete povolit zobrazení [C++] pro nativní hodnoty v okně Místní hodnoty. Tato funkce není ve výchozím nastavení povolená.

  • Pokud chcete tuto funkci povolit, klikněte pravým tlačítkem v okně Místní hodnoty a nastavte možnost nabídky Zobrazit uzly zobrazení jazyka Python>C++.

    Snímek obrazovky, který ukazuje, jak povolit možnosti Zobrazit uzly zobrazení C++ pro okno Místní hodnoty

  • Uzel [zobrazení C++] poskytuje reprezentaci základní struktury C/C++ pro hodnotu, která je identická s tím, co vidíte v nativním rámci. Zobrazuje instanci _longobject (pro kterou PyLongObject je typedef) pro dlouhé celé číslo Pythonu a snaží se odvodit typy pro nativní třídy, které sami vytvoříte. Podřízené položky tohoto uzlu se dají upravovat.

    Snímek obrazovky znázorňující zobrazení C++ v okně Místní hodnoty v sadě Visual Studio

Pokud je podřízené pole objektu typu PyObjectnebo jiného podporovaného typu, má uzel reprezentace [zobrazení Pythonu] (pokud jsou tyto reprezentace povolené). Díky tomuto chování můžete procházet grafy objektů, ve kterých nejsou odkazy přímo vystavené Pythonu.

Na rozdíl od uzlů [zobrazení Pythonu] využívajících metadata objektu Pythonu k určení typu objektu neexistuje podobný mechanismus pro [zobrazení C++]. Obecně řečeno, vzhledem k hodnotě Pythonu (tj PyObject . odkazu) není možné spolehlivě určit, která struktura C/C++ ji podporuje. Ladicí program smíšeného režimu se pokusí typ odhadnout tak, že se podívá na různá pole typu objektu (například PyTypeObject odkazovaná podle jeho ob_type pole), která mají typy ukazatelů funkce. Pokud některý z těchto ukazatelů funkce odkazuje na funkci, která se dá přeložit, a tato funkce má self parametr s typem konkrétnějším než PyObject*, předpokládá se, že se jedná o záložní typ.

Podívejte se na následující příklad, kde ob_type->tp_init hodnota daného objektu odkazuje na následující funkci:

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

V tomto případě ladicí program může správně odvodit, že typ jazyka C objektu je FobObject. Pokud ladicí program nedokáže určit přesnější typ z tp_init, přesune se do jiných polí. Pokud nelze odvodit typ z některého z těchto polí, uzel [zobrazení C++] zobrazí objekt jako PyObject instanci.

Pokud chcete vždy získat užitečnou reprezentaci pro vlastní vytvořené typy, je nejlepší při registraci typu zaregistrovat aspoň jednu speciální funkci a použít parametr silného typu self . Většina typů tento požadavek splňuje přirozeně. Pro jiné typy je tp_init kontrola obvykle nejpohodlnější vstup pro tento účel. Fiktivní implementace tp_init pro typ, který je k dispozici pouze pro povolení odvození typu ladicího programu, může okamžitě vrátit nula, stejně jako v předchozím příkladu.

Kontrola rozdílů oproti standardnímu ladění Pythonu

Ladicí program smíšeného režimu se liší od standardního ladicího programu Pythonu. Představuje některé další funkce, ale chybí některé funkce související s Pythonem, a to následujícím způsobem:

  • Mezi nepodporované funkce patří podmíněné zarážky, okno Debug Interactive a vzdálené ladění napříč platformami.
  • Okno Okamžité je k dispozici, ale s omezenou podmnožinou jeho funkcí, včetně všech omezení uvedených v této části.
  • Podporované verze Pythonu zahrnují pouze CPython 2.7 a 3.3+.
  • Pokud chcete použít Python se sadou Visual Studio Shell (například pokud ho nainstalujete pomocí integrovaného instalačního programu), Visual Studio nemůže otevřít projekty C++. V důsledku toho je prostředí pro úpravy pro soubory C++ pouze v základním textovém editoru. Ladění C/C++ a ladění ve smíšeném režimu jsou však plně podporovány v prostředí se zdrojovým kódem, krokováním do nativního kódu a vyhodnocením výrazu C++ v oknech ladicího programu.
  • Při zobrazení objektů Pythonu v oknech nástrojů Locals a Watch debugger zobrazí ladicí program smíšeného režimu pouze strukturu objektů. Nevyhodnocuje automaticky vlastnosti ani nezobrazuje vypočítané atributy. U kolekcí zobrazuje pouze prvky pro předdefinované typy kolekcí (tuple, list, dict, set). Vlastní typy kolekcí nejsou vizualizovány jako kolekce, pokud nejsou zděděny z některého předdefinovaného typu kolekce.
  • Vyhodnocení výrazu se zpracovává, jak je popsáno v následující části.

Použití vyhodnocení výrazu

Standardní ladicí program Pythonu umožňuje vyhodnocení libovolných výrazů Pythonu v oknech Kukátku a Okamžité , pokud je laděný proces pozastavený v libovolném bodě kódu, pokud není blokován v vstupně-výstupní operaci nebo jiném podobném systémovém volání. V ladění ve smíšeném režimu lze libovolné výrazy vyhodnotit pouze v případě, že se zastaví v kódu Pythonu, po zarážce nebo při přechodu do kódu. Výrazy lze vyhodnotit pouze ve vlákně, na kterém došlo k zarážce nebo operaci krokování.

Když se ladicí program zastaví v nativním kódu nebo v kódu Pythonu, kde se popsané podmínky nepoužijí, například po operaci krokování nebo v jiném vlákně). Vyhodnocení výrazů je omezené na přístup k místním a globálním proměnným v oboru aktuálně vybraného rámce, přístupu k jejich polím a indexování předdefinovaných typů kolekcí pomocí literálů. Například následující výraz lze vyhodnotit v libovolném kontextu (za předpokladu, že všechny identifikátory odkazují na existující proměnné a pole odpovídajících typů):

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

Ladicí program smíšeného režimu také tyto výrazy překládá odlišně. Všechny operace přístupu členů vyhledávají pouze pole, která jsou přímo součástí objektu (například položka v jeho __dict__ objektu nebo __slots__nebo pole nativní struktury vystavené Pythonu prostřednictvímtp_members) a ignorují libovolnou __getattr____getattribute__logiku , nebo popisovače. Podobně všechny operace indexování ignorují __getitem__a přistupují přímo k vnitřním datovým strukturám kolekcí.

V zájmu konzistence se toto schéma překladu názvů používá pro všechny výrazy, které odpovídají omezením pro vyhodnocení omezeného výrazu. Toto schéma se použije bez ohledu na to, zda jsou v aktuálním bodu zastavení povoleny libovolné výrazy. Pokud chcete vynutit správnou sémantiku Pythonu, pokud je k dispozici plnohodnotný vyhodnocovací modul, uzavřete výraz do závorek:

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