2013-06-12 12 views
15

Sto provando a eseguire il debug di una CLI Python che ho scritto che può prendere i suoi argomenti da stdin. Un semplice caso di test dovrebbe avere l'output diCome eseguire il debug di CLI Python che richiede stdin?

echo "test" | python mytool.py 

essere equivalente alla produzione di

python mytool.py test 

mi piacerebbe eseguire il debug di alcuni problemi con questo strumento, quindi ho cercato di eseguire questo:

echo "test" | pdb mytool.py 

Ma ho questa uscita, uscite poi PDB:

> /path/to/mytool.py(5)<module>() 
-> ''' 
(Pdb) *** NameError: name 'test' is not defined 
(Pdb) 

La stessa cosa si verifica quando aggiungo -m python allo shebang e se eseguo pdb.set_trace() all'interno dello script.

Cosa sta succedendo qui?

+2

È possibile modificare lo script per accettare l'input da un file diverso da stdin? – nmichaels

+0

possibile duplicato di [test dell'unità di programma CLI Python] (http://stackoverflow.com/questions/13493288/python-cli-program-test-testing) –

+1

@ user1901786 Come si accede allo stdin nello script CLI? Usando 'sys.stdin'? Inoltre, vuoi solo scrivere un test per questo o hai bisogno di avviare il debugger all'interno dello script? Se hai bisogno del debugger, a che punto vuoi coinvolgere lo script? Scusa, la domanda mi è un po 'oscura. – famousgarkin

risposta

0

Quando si utilizza pdb (o qualsiasi altro debugger Python) acquisisce stdin per i comandi di debug, ecco perché si ottiene NameError: name 'test' is not defined.

Per esempio questo comando uscire debugger alla supplica di un runtime e voi non ottenere questo errore (né il debug interattivo) per una corsa:

(eco cont; echo "test") | python -m pdb mytool.py

+2

Mentre questo spiega cosa sta succedendo, non fornisce una risposta. – whereswalden

3

È possibile utilizzare un altro descrittore di file. Con bash è possibile creare un nuovo descrittore di file con:

exec 3<> test.txt 

E poi sul file pitone hai qualcosa di simile:

#!/usr/bin/python 

# Use fd 3 as another stdin file. 
import os 
stdin=os.fdopen(3) 

while True: 
    s=stdin.readline() 
    import pdb; pdb.set_trace() 
    print len(s) 

Basta runing lo script utilizzerà che test.txt come input, e si può usare lo stdin sullo stdin. Può essere usato anche con i tubi, se necessario.

+3

Preferirei una soluzione che non richieda la modifica del codice dello strumento. – whereswalden

9

Un'altra opzione è creare il proprio oggetto Pdb e impostare lì lo stdin e lo stdout. Il mio proof of concept riguarda 2 terminali, ma di sicuro alcuni lavori possono essere uniti a qualche tipo di server di rete molto insicuro.

  1. Creare due FIFO: mkfifo stdin mkfifo stdout

  2. In un terminale, stdout aperta su sfondo, e scrivere stdin: cat stdout & cat > stdin

  3. Nel codice python/console creare l'oggetto pdb, e usalo: import pdb mypdb=pdb.Pdb(stdin=open('stdin','r'), stdout=open('stdout','w')) ... mypdb.set_trace() ...
  4. Utile!

Dovresti essere in grado di utilizzare pdb sulla prima console.

L'unico inconveniente è dover utilizzare il PDB personalizzato, ma alcuni scimmia patch a init (PYTHONSTARTUP o simile) può aiutare:

import pdb mypdb=pdb.Pdb(stdin=open('stdin','r'), stdout=open('stdout','w')) pdb.set_trace=mydbp.set_trace

0

tuo controllando TTY è ancora un terminale, giusto? Utilizzare questo invece di pdb.set_trace.

def tty_pdb(): 
    from contextlib import (_RedirectStream, 
          redirect_stdout, redirect_stderr) 
    class redirect_stdin(_RedirectStream): 
     _stream = 'stdin' 
    with open('/dev/tty', 'r') as new_stdin, \ 
     open('/dev/tty', 'w') as new_stdout, \ 
     open('/dev/tty', 'w') as new_stderr, \ 
     redirect_stdin(new_stdin), \ 
     redirect_stdout(new_stdout), redirect_stderr(new_stderr): 
     __import__('pdb').set_trace() 

In questa situazione, non è stato possibile eseguire la lettura automatica del completamento automatico. La freccia su non funzionerà neanche, o qualsiasi altra delle sottigliezze readline.

Problemi correlati