Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
La maggior parte dei normali debugger Python supporta solo il debug del codice Python, ma è pratica comune per gli sviluppatori usare Python con C o C++. Alcuni scenari che usano codice misto sono applicazioni che richiedono prestazioni elevate o la possibilità di richiamare direttamente le API della piattaforma vengono spesso codificate in Python e C o C++.
Visual Studio offre il debug in modalità mista integrata e simultanea per il codice C/C++ nativo e Python. Il supporto è disponibile quando si seleziona l'opzione Strumenti di sviluppo nativo Python per il carico di lavoro Sviluppo Python nel programma di installazione di Visual Studio:
In questo articolo viene illustrato come usare le funzionalità di debug in modalità mista seguenti:
- Stack di chiamate combinato
- Passaggio tra Python e codice nativo
- Punti di interruzione in entrambi i tipi di codice
- Visualizzare le rappresentazioni Python degli oggetti in frame nativi e viceversa
- Debug all'interno del contesto del progetto Python o del progetto C++
Prerequisiti
Visual Studio 2017 e versioni successive. Il debug in modalità mista non è disponibile con Python Tools per Visual Studio 1.x in Visual Studio 2015 e versioni precedenti.
Visual Studio installato con il supporto per i carichi di lavoro Python. Per altre informazioni, vedere Installare il supporto python in Visual Studio.
Abilitare il debug in modalità mista in un progetto Python
I passaggi seguenti descrivono come abilitare il debug in modalità mista in un progetto Python:
In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto Python e scegliere Proprietà.
Nel riquadro Proprietà selezionare la scheda Debug e quindi selezionare l'opzione Debug>Abilita debug del codice nativo :
Questa opzione abilita la modalità mista per tutte le sessioni di debug.
Suggerimento
Quando si abilita il debug del codice nativo, la finestra di output di Python potrebbe chiudersi immediatamente dopo che il programma è terminato, senza fermarsi per visualizzare il prompt Press any key to continue. Per forzare la pausa e la richiesta dopo aver abilitato il debug del codice nativo, aggiungere l'argomento
-ial campo di esecuzione>Argomenti dell'interprete nella scheda Debug. Questo argomento inserisce l'interprete Python in modalità interattiva dopo l'esecuzione del codice. Il programma attende di selezionare CTRL+Z+Invio per chiudere la finestra.Selezionare Salva file> (o CTRL+) per salvare le modifiche alle proprietà.
Per collegare il debugger in modalità mista a un processo esistente, selezionare Debug>Connetti a processo. Verrà visualizzata una finestra di dialogo.
Nella finestra di dialogo Connetti a processo selezionare il processo appropriato dall'elenco.
Per il campo Connetti a , usare l'opzione Seleziona per aprire la finestra di dialogo Seleziona tipo di codice .
Nella finestra di dialogo Seleziona tipo di codice scegliere l'opzione Debug di questi tipi di codice .
Nell'elenco selezionare la casella di controllo Python (nativa) e selezionare OK:
Selezionare Connetti per avviare il debugger.
Le impostazioni del tipo di codice sono persistenti. Se si vuole disabilitare il debug in modalità mista e collegarsi a un processo diverso in un secondo momento, deselezionare la casella di controllo Tipo di codice Python (nativo) e selezionare la casella di controllo Tipo di codice nativo .
È possibile selezionare altri tipi di codice oltre a o anziché l'opzione Nativa . Ad esempio, se un'applicazione gestita ospita CPython, che a sua volta usa moduli di estensione nativi e si vuole eseguire il debug di tutti e tre i progetti di codice, selezionare le caselle di controllo Python, Native e Managed . Questo approccio offre un'esperienza di debug unificata, inclusi gli stack di chiamate combinati e lo spostamento tra tutti e tre i runtime.
Usare ambienti virtuali
Quando si usa questo metodo di debug in modalità mista per gli ambienti virtuali (venvs), Python per Windows usa un python.exe file stub per venvs che Visual Studio trova e carica come sottoprocesso.
Per Python 3.8 e versioni successive, la modalità mista non supporta il debug multiprocesso. Quando si avvia la sessione di debug, il sottoprocesso stub viene sottoposto a debug anziché all'applicazione. Per gli scenari di collegamento, la soluzione alternativa consiste nell'allegare al file corretto
python.exe. Quando si avvia l'applicazione con il debug ,ad esempio tramite il tasto di scelta rapida F5 , è possibile creare il venv usando il comandoC:\Python310-64\python.exe -m venv venv --symlinks. Nel comando inserire la versione preferita di Python. Per impostazione predefinita, solo gli amministratori possono creare collegamenti simbolici in Windows.Per le versioni di Python precedenti alla 3.8, il debug in modalità mista dovrebbe funzionare come previsto con venvs.
L'esecuzione in un ambiente globale non causa questi problemi per alcuna versione di Python.
Installare simboli Python
Quando si avvia il debug in modalità mista per la prima volta, è possibile che venga visualizzata una finestra di dialogo Simboli Python necessari . È necessario installare i simboli una sola volta per qualsiasi ambiente Python specifico. I simboli vengono inclusi automaticamente se si installa il supporto python tramite il programma di installazione di Visual Studio (Visual Studio 2017 e versioni successive). Per altre informazioni, vedere Installare i simboli di debug per gli interpreti Python in Visual Studio.
Accedere al codice sorgente Python
È possibile rendere disponibile il codice sorgente per Python standard durante il debug.
Passare a
https://www.python.org/downloads/source/.Scaricare l'archivio del codice sorgente Python appropriato per la versione e estrarre il codice in una cartella.
Quando Visual Studio richiede il percorso del codice sorgente Python, puntare ai file specifici nella cartella di estrazione.
Abilitare il debug in modalità mista in un progetto C/C++
Visual Studio 2017 versione 15.5 e successive supporta il debug in modalità mista da un progetto C/C++. Un esempio di questo utilizzo è quando si vuole incorporare Python in un'altra applicazione, come descritto in python.org.
I passaggi seguenti descrivono come abilitare il debug in modalità mista per un progetto C/C++:
In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto C/C++ e scegliere Proprietà.
Nel riquadro Proprietà, scegliere la scheda Proprietà di configurazione>Debug.
Espandi il menu a discesa per l'opzione Debugger da avviare e seleziona Debugging Python/Nativo.
Annotazioni
Se non viene visualizzata l'opzione Debug python/nativo , è prima necessario installare gli strumenti di sviluppo nativi Python usando il programma di installazione di Visual Studio. L'opzione di debug nativo è disponibile nell'ambito di sviluppo Python. Per altre informazioni, vedere Installare il supporto python in Visual Studio.
Selezionare OK per salvare le modifiche.
Effettuare il debug della struttura di avvio del programma
Quando si usa questo metodo, non è possibile eseguire il debug dell'utilità di avvio del py.exe programma perché genera un sottoprocesso figlio python.exe . Il debugger non è collegato al sottoprocesso. Per questo scenario, la soluzione alternativa consiste nell'avviare il python.exe programma direttamente con argomenti, come indicato di seguito:
Nel riquadro Pagine delle proprietà per il progetto C/C++ andare alla scheda Proprietà di configurazione>Debug.
Per l'opzione Comando specificare il percorso completo del file di
python.exeprogramma.Specificare gli argomenti desiderati nel campo Argomenti comando .
Collegare il debugger in modalità mista
Per Visual Studio 2017 versione 15.4 e precedenti, il debug in modalità mista diretta è abilitato solo quando si avvia un progetto Python in Visual Studio. Il supporto è limitato perché i progetti C/C++ usano solo il debugger nativo.
Per questo scenario, la soluzione alternativa consiste nel collegare il debugger separatamente:
Avvia il progetto C++ senza debug selezionando Debug>Avvia senza debug o usa la scorciatoia da tastiera Ctrl+F5.
Per collegare il debugger in modalità mista a un processo esistente, selezionare Debug>Connetti a processo. Verrà visualizzata una finestra di dialogo.
Nella finestra di dialogo Connetti a processo selezionare il processo appropriato dall'elenco.
Per il campo Connetti a , usare l'opzione Seleziona per aprire la finestra di dialogo Seleziona tipo di codice .
Nella finestra di dialogo Seleziona tipo di codice scegliere l'opzione Debug di questi tipi di codice .
Nell'elenco selezionare la casella di controllo Python e selezionare OK.
Selezionare Connetti per avviare il debugger.
Suggerimento
È possibile aggiungere una pausa o un ritardo nell'applicazione C++ per assicurarsi che non chiami il codice Python di cui si vuole eseguire il debug prima di collegare il debugger.
Esplorare le funzionalità specifiche della modalità mista
Visual Studio offre diverse funzionalità di debug in modalità mista per semplificare il debug dell'applicazione:
- Stack di chiamate combinato
- Passaggio tra Python e codice nativo
- Visualizzazione dei valori PyObject nel codice nativo
- Visualizzazione dei valori nativi nel codice Python
Usare uno stack di chiamate combinato
La finestra Pila di chiamate mostra i frame dello stack sia nativi che Python intercalati, con le transizioni contrassegnate tra i due elementi.
- Per eseguire transizioni come [Codice esterno] senza specificare la direzione della transizione, usare il riquadro Opzioni strumenti>. Espandere la sezione Tutte le impostazioni>Debug>generale , selezionare la casella di controllo Abilita Just My Code .
- Per eseguire transizioni come [Codice esterno] senza specificare la direzione della transizione, usare la finestra di dialogo Opzioni strumenti>. Espandere la sezione Debug>generale , selezionare la casella di controllo Abilita Just My Code e quindi selezionare OK.
- Per rendere attivo qualsiasi fotogramma di chiamata, fare doppio clic sul fotogramma. Questa azione apre anche il codice sorgente corrispondente, se possibile. Se il codice sorgente non è disponibile, il frame viene ancora reso attivo e le variabili locali possono essere esaminate.
Passaggio tra Python e codice nativo
Visual Studio fornisce i comandi Esegui istruzione (F11) o Esci (Maiusc+F11) per consentire al debugger in modalità mista di gestire correttamente le modifiche tra i tipi di codice.
Quando Python chiama un metodo di un tipo implementato in C, l'esecuzione di istruzioni su una chiamata a tale metodo si arresta all'inizio della funzione nativa che implementa il metodo .
Questo stesso comportamento si verifica quando il codice nativo chiama una funzione API Python che comporta la chiamata al codice Python. L'esecuzione di una chiamata a
PyObject_CallObjectsu un valore di funzione originariamente definito in Python si arresta all'inizio della funzione Python.Passare da Python a codice nativo è anche supportato per le funzioni native invocate da Python tramite ctypes.
Usare la visualizzazione dei valori PyObject nel codice nativo
Quando un frame nativo (C o C++) è attivo, le variabili locali sono visualizzate nella finestra Variabili locali del debugger. Nei moduli di estensione Python nativi, molte di queste variabili sono di tipo PyObject (ovvero un typedef per _object) o altri tipi di Python fondamentali. Nel debug in modalità mista, questi valori presentano un altro nodo figlio con etichetta [visualizzazione Python].
Per visualizzare la rappresentazione Python della variabile, espandere il nodo. La visualizzazione delle variabili è identica a quella visualizzata se una variabile locale che fa riferimento allo stesso oggetto è presente in un frame Python. Gli elementi figlio di questo nodo sono modificabili.
Per disabilitare questa funzionalità, fare clic con il pulsante destro del mouse in un punto qualsiasi della finestra Variabili locali e attivare o disattivare l'opzione di menuMostra nodi visualizzazione Python>:
Tipi C che mostrano i nodi di visualizzazione Python
I tipi C seguenti mostrano i nodi [visualizzazione Python] , se abilitati:
PyObjectPyVarObjectPyTypeObjectPyByteArrayObjectPyBytesObjectPyTupleObjectPyListObjectPyDictObjectPySetObjectPyIntObjectPyLongObjectPyFloatObjectPyStringObjectPyUnicodeObject
[Visualizzazione Python] non viene visualizzato automaticamente per i tipi creati manualmente. Quando si creano estensioni per Python 3.x, questa mancanza non è in genere un problema. Qualsiasi oggetto, in definitiva, ha un ob_base campo di uno dei tipi C elencati, il che fa apparire [visualizzazione Python].
Visualizzare i valori nativi nel codice Python
È possibile abilitare una [visualizzazione C++] per i valori nativi nella finestra Variabili locali quando un frame Python è attivo. Questa funzionalità non è abilitata per impostazione predefinita.
Per abilitare la funzionalità, fare clic con il pulsante destro del mouse nella finestra Variabili locali e impostare l'opzione> di menuPython Show C++ View Nodes (Mostra nodi visualizzazione C++).
Il nodo [visualizzazione C++] fornisce una rappresentazione della struttura C/C++ sottostante per un valore, identico a quello visualizzato in un frame nativo. Mostra un'istanza di
_longobject(per cuiPyLongObjectè un typedef) per un intero lungo Python e tenta di inferire i tipi per le classi native che hai creato tu stesso. I figli di questo nodo sono modificabili.
Se un campo figlio di un oggetto è di tipo PyObjecto un altro tipo supportato, ha un nodo di rappresentazione [visualizzazione Python] (se tali rappresentazioni sono abilitate). Questo comportamento consente di esplorare gli oggetti grafici in cui i collegamenti non sono esposti direttamente a Python.
A differenza dei nodi [visualizzazione Python] , che usano i metadati dell'oggetto Python per determinare il tipo dell'oggetto, non esiste un meccanismo similemente affidabile per [visualizzazione C++].. In generale, dato un valore Python (ovvero un PyObject riferimento) non è possibile determinare in modo affidabile quale struttura C/C++ lo supporta. Il debugger in modalità mista tenta di determinare il tipo esaminando vari campi del tipo dell'oggetto (ad esempio il PyTypeObject, riferito dal suo campo ob_type) che sono di tipo puntatore a funzione. Se uno di questi puntatori di funzione fa riferimento a una funzione che può essere risolta e tale funzione ha un parametro con un tipo self più specifico rispetto a PyObject*, si presuppone che tale tipo sia il tipo di base.
Si consideri l'esempio seguente, dove il ob_type->tp_init valore per di un determinato oggetto punta alla funzione seguente:
static int FobObject_init(FobObject* self, PyObject* args, PyObject* kwds) {
return 0;
}
In questo caso, il debugger può dedurre correttamente che il tipo C dell'oggetto è FobObject. Se il debugger non riesce a determinare un tipo più preciso da tp_init, passa ad altri campi. Se non è possibile dedurre il tipo da uno di questi campi, il nodo [visualizzazione C++] presenta l'oggetto come PyObject istanza.
Per ottenere sempre una rappresentazione utile per i tipi creati personalizzati, è consigliabile registrare almeno una funzione speciale durante la registrazione del tipo e usare un parametro fortemente tipizzato self . La maggior parte dei tipi soddisfa naturalmente tale requisito. Per altri tipi, l'ispezione tp_init è in genere l'opzione più pratica da utilizzare per questo scopo. Un'implementazione fittizia di tp_init per un tipo presente esclusivamente per abilitare l'inferenza del tipo di debugger può restituire immediatamente zero, come nell'esempio precedente.
Esaminare le differenze rispetto al debug Python standard
Il debugger in modalità mista è distinto dal debugger Python standard. Introduce alcune funzionalità aggiuntive, ma non include alcune funzionalità correlate a Python, come indicato di seguito:
- Le funzionalità non supportate includono punti di interruzione condizionali, la finestra Debug interattivo e il debug remoto multipiattaforma.
- La finestra Immediata è disponibile, ma con un subset limitato delle relative funzionalità, incluse tutte le limitazioni elencate in questa sezione.
- Le versioni di Python supportate includono solo CPython 2.7 e 3.3+.
- Per usare Python con Visual Studio Shell (ad esempio, se si installa con il programma di installazione integrato), Visual Studio non è in grado di aprire progetti C++. Di conseguenza, l'esperienza di modifica per i file C++ è solo quella di un editor di testo di base. Tuttavia, il debug C/C++ e il debug in modalità mista sono completamente supportati in Shell con il codice sorgente, l'esecuzione di istruzioni nel codice nativo e la valutazione delle espressioni C++ nelle finestre del debugger.
- Quando si visualizzano oggetti Python nelle finestre degli strumenti Variabili locali e Osservazione, il debugger in modalità mista mostra solo la struttura degli oggetti. Non valuta automaticamente le proprietà o mostra gli attributi calcolati. Per le raccolte, vengono visualizzati solo gli elementi per i tipi di raccolta predefiniti (
tuple,list,dict,set). I tipi di raccolta personalizzati non vengono visualizzati come raccolte, a meno che non vengano ereditati da un tipo di raccolta predefinito. - La valutazione delle espressioni viene gestita come descritto nella sezione seguente.
Usare la valutazione delle espressioni
Il debugger standard di Python consente di valutare espressioni arbitrarie di Python nelle finestre Watch e Immediate quando il processo in debug è sospeso in qualsiasi punto del codice, purché non sia bloccato in un'operazione di I/O o in altre chiamate di sistema simili. Nel debug in modalità mista, le espressioni arbitrarie possono essere valutate solo quando vengono arrestate nel codice Python, dopo un punto di interruzione o quando si esegue l'istruzione nel codice. Le espressioni possono essere valutate solo nel thread in cui si è verificato il punto di interruzione o l'operazione di passo.
Quando il debugger si arresta nel codice nativo o nel codice Python in cui le condizioni descritte non si applicano, ad esempio dopo un'operazione di passaggio o in un thread diverso. La valutazione delle espressioni è limitata all'accesso alle variabili locali e globali nell'ambito del frame attualmente selezionato, all'accesso ai relativi campi e all'indicizzazione dei tipi di raccolta predefiniti con valori letterali. Ad esempio, l'espressione seguente può essere valutata in qualsiasi contesto (purché tutti gli identificatori facciano riferimento a variabili e campi esistenti di tipi appropriati):
foo.bar[0].baz['key']
Il debugger in modalità mista risolve anche tali espressioni in modo diverso. Tutte le operazioni di accesso ai membri cercano solo i campi che fanno direttamente parte dell'oggetto (ad esempio una voce nel relativo __dict__ o __slots__, o un campo di uno struct nativo esposto a Python tramite tp_members) e ignorano qualsiasi __getattr__ o __getattribute__, o logica di descrittore. Analogamente, tutte le operazioni di indicizzazione ignorano __getitem__ e accedono direttamente alle strutture dati interne delle raccolte.
Per garantire la coerenza, questo schema di risoluzione dei nomi viene usato per tutte le espressioni che corrispondono ai vincoli per la valutazione limitata delle espressioni. Questo schema viene applicato indipendentemente dal fatto che le espressioni arbitrarie siano consentite nel punto di arresto corrente. Per forzare la semantica Python corretta quando è disponibile un analizzatore completo, racchiudere l'espressione tra parentesi:
(foo.bar[0].baz['key'])