Sto scrivendo un piccolo IDE python e voglio aggiungere un semplice debug. Non ho bisogno di tutte le funzionalità di winpdb. Come si avvia un programma python (per nome file) con un punto di interruzione impostato su un numero di riga in modo che venga eseguito fino a quel numero di riga e si fermi? Nota che non voglio farlo dalla riga di comando, e non voglio modificare l'origine (inserendo set_trace, ad esempio). E non voglio che si fermi alla prima riga, quindi devo eseguire il debugger da lì. Ho provato tutti i modi ovvi con pdb e bdb, ma mi manca qualcosa.Esecuzione di una sessione di debug di Python da un programma, non dalla console
risposta
Praticamente l'unico modo praticabile per farlo (per quanto ne so) è eseguire Python come sottoprocesso dall'interno dell'IDE. Questo evita "inquinamento" dall'attuale interprete Python, il che rende abbastanza probabile che il programma funzioni come se fosse stato avviato in modo indipendente. (Se avete problemi con questo, controllare l'ambiente sottoprocesso.) In questo modo, è possibile eseguire uno script in "modalità debug" usando
p = subprocess.Popen(args=[sys.executable, '-m', 'pdb', 'scriptname.py', 'arg1'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
Questo avvierà Python al prompt del debugger. Avrete bisogno di eseguire alcuni comandi del debugger per impostare i punti di interruzione, che si può fare in questo modo:
o,e = p.communicate('break scriptname.py:lineno')
Se funziona, o
dovrebbe essere l'uscita normale dell'interprete Python dopo che imposta un punto di interruzione, e dovrebbe e
essere vuoto Ti suggerirei di giocare con questo e aggiungere alcuni controlli nel codice per assicurarti che i punti di interruzione siano stati impostati correttamente.
Dopo di che, si può avviare il programma in esecuzione con
p.communicate('continue')
A questo punto si sarebbe probabilmente desidera agganciare l'input, output, e l'errore torrenti fino alla console che si sta incorporando nel vostro IDE. Si sarebbe probabilmente bisogno di fare questo con un ciclo di eventi, più o meno in questo modo:
while p.returncode is None:
o,e = p.communicate(console.read())
console.write(o)
console.write(e)
si dovrebbe considerare che frammento di essere efficace pseudocodice, dal momento che a seconda di come esattamente le tue opere di console, che probabilmente richiederà un certo armeggiare per fallo bene
Se questo vi sembra troppo disordinato, probabilmente si può semplificare il processo un po 'con le caratteristiche di pdb
e bdb
moduli di Python (sto cercando di indovinare "debugger Python" e debugger di base", rispettivamente). Il miglior riferimento su come fare questo è il codice sorgente del modulo pdb
. Fondamentalmente, il modo in cui le responsabilità dei moduli sono suddivise è che bdb
gestisce la funzionalità del debugger "sotto il cofano", come l'impostazione dei punti di interruzione o l'arresto e il riavvio dell'esecuzione, pdb
è un wrapper attorno a questo che gestisce l'interazione dell'utente, vale a dire la lettura dei comandi e la visualizzazione dell'output
Per il debugger integrato in IDE, sarebbe opportuno regolare t il comportamento del modulo pdb
in due modi che mi viene in mente:
- ho impostato automaticamente i punti di interruzione durante l'inizializzazione, senza dover inviare esplicitamente testuale comanda di farlo
- rendono prende input da e invia l'output alla tua console IDE
Queste due modifiche devono essere facilmente implementate dalla sottoclasse pdb.Pdb
.È possibile creare una sottoclasse cui inizializzatore prende una lista di punti di interruzione come un ulteriore argomento:
class MyPDB(pdb.Pdb):
def __init__(self, breakpoints, completekey='tab',
stdin=None, stdout=None, skip=None):
pdb.Pdb.__init__(self, completekey, stdin, stdout, skip)
self._breakpoints = breakpoints
il posto più logico per impostare in realtà i punti di interruzione è solo dopo il debugger legge il .pdbrc
file, che si verifica nel metodo pdb.Pdb.setup
. Per eseguire la configurazione attuale, utilizzare il metodo set_break
ereditato da bdb.Bdb
:
def setInitialBreakpoints(self):
_breakpoints = self._breakpoints
self._breakpoints = None # to avoid setting breaks twice
for bp in _breakpoints:
self.set_break(filename=bp.filename, line=bp.line,
temporary=bp.temporary, conditional=bp.conditional,
funcname=bp.funcname)
def setup(self, f, t):
pdb.Pdb.setup(self, f, t)
self.setInitialBreakpoints()
Questo pezzo di codice funzionerebbe per ciascun punto di interruzione essendo passata come ad esempio una tupla chiamata Potresti anche sperimentare semplicemente la creazione di istanze bdb.Breakpoint
direttamente, ma non sono sicuro che funzioni correttamente, dal momento che bdb.Bdb
mantiene le proprie informazioni sui punti di interruzione.
Successivamente, sarà necessario creare un nuovo metodo main
per il modulo che lo esegue nello stesso modo nell'esecuzione di pdb
. In una certa misura, è possibile copiare il metodo main
da pdb
(e la dichiarazione if __name__ == '__main__'
ovviamente), ma sarà necessario aumentarlo in qualche modo per passare le informazioni relative ai punti di interruzione aggiuntivi. Quello che suggerisco è scrivere i punti di interruzione in un file temporaneo presso il vostro IDE, e passando il nome di quel file come secondo argomento:
tmpfilename = ...
# write breakpoint info
p = subprocess.Popen(args=[sys.executable, '-m', 'mypdb', tmpfilename, ...], ...)
# delete the temporary file
Poi, nel mypdb.main()
, si dovrebbe aggiungere qualcosa di simile:
def main():
# code excerpted from pdb.main()
...
del sys.argv[0]
# add this
bpfilename = sys.argv[0]
with open(bpfilename) as f:
# read breakpoint info
breakpoints = ...
del sys.argv[0]
# back to excerpt from pdb.main()
sys.path[0] = os.path.dirname(mainpyfile)
pdb = Pdb(breakpoints) # modified
Ora è possibile utilizzare il nuovo modulo di debugger proprio come si farebbe con lo pdb
, con la differenza che non è necessario inviare esplicitamente comandi break
prima dell'avvio del processo. Questo ha il vantaggio di poter collegare direttamente lo standard input e output del subprocesso Python alla tua console, se ti permette di farlo.
Grazie per l'input. Ma ottengo ValueError: operazione I/O su file chiuso non appena arriva a p.communicate ('continue'). Utilizzo close_fds = False nel Popen non aiuta ... –
@antwin: ricorda che tutto questo è essenzialmente pseudocodice. Se lo esegui così com'è, ovviamente avrai tutti i tipi di errori. Devi adattarlo al tuo progetto, in modi in cui non potrei dirti nulla senza avere accesso al tuo codice sorgente. –
Davvero! Così ho estratto il tuo suggerimento nel seguente file #!/Usr/bin/python import sys, subprocess fileName = '/tmp/test.py' lineno = 4 p = subprocess.Popen (args = [sys.executable , '-m', 'pdb', nome del file], stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.STDOUT) cmd = 'rottura% s:% d' % (filename, lineno stampa cmd o, e = p.communicate (cmd) p.communicate ('continue') Dovrebbe funzionare, e ho già usato simili in precedenza, ma restituisce comunque ValueError: operazione I/O su file chiuso dopo la prima comunicata ... –
- 1. Problemi di debug di un semplice programma di console :: CLion
- 2. E 'possibile associare una sessione di debug a un programma in esecuzione in eclissi CDT
- 3. Esecuzione di un programma di console C++ a schermo intero
- 4. Esecuzione di un programma java da un altro programma java
- 5. Debug di un processo Python in esecuzione
- 6. Esecuzione di un programma/script da QMake
- 7. Esecuzione di un programma Java da Command Line Linux
- 8. Come posso uscire dall'uscita di un programma di console C++?
- 9. Stop Application Insights dalla pubblicazione sulla console di debug
- 10. Esecuzione di un comando linux da python
- 11. Programma di debug XQuery
- 12. programma di console semplice non uscirà se cudaMalloc si chiama
- 13. Eclipse CDT La console di debug non visualizza l'output del programma
- 14. Esecuzione di file Jar da Python
- 15. Programma di esecuzione CLion nel terminale di sistema separato
- 16. L'esecuzione di un programma mi dà risultati diversi dalla modalità di debug
- 17. La finestra del programma di debug non si chiude
- 18. C - Esecuzione di un programma nella RAM
- 19. Esecuzione di un metodo/funzione python direttamente da un file
- 20. Modo corretto per ricaricare un modulo python dalla console
- 21. Esecuzione di un mini-programma in Mono.Csharp
- 22. Chiusura sessione ssh -X con un programma GUI in esecuzione, ma lasciando il programma in esecuzione sull'host remoto
- 23. Eclipse - Programmi in esecuzione non nella console nativa di eclipse
- 24. Esecuzione di un programma Java in background in Tomcat
- 25. Esecuzione di un programma MATLAB con argomenti
- 26. Come sapere se è in esecuzione in una console linux rispetto a una sessione ssh?
- 27. Posso staccare un oggetto da una sessione di NHibernate?
- 28. Come posso scoprire se un programma è in esecuzione da riga di comando o dal web?
- 29. Convertire un programma Java Console in Webapp
- 30. Esempio di debug di asyncio di Python
Quindi non si desidera utilizzare la riga di comando e non si desidera modificare la sorgente ... a quale altro modo si sta pensando? – Amber