2013-06-12 16 views
15

Próbuję debugować interfejs CLI w języku Python, który napisałem, który może wziąć swoje argumenty ze standardowego wejścia. Prosty sprawdzian miałoby wyjścieJak debugować Pythona CLI, który przyjmuje stdin?

echo "test" | python mytool.py 

równoznaczne z wyjściem

python mytool.py test 

chciałbym debugować kilka problemów z tym narzędziem, więc próbowałem uruchomić to:

echo "test" | pdb mytool.py 

Ale mam to wyjście, a następnie wyjść pdb:

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

To samo dzieje się, gdy dodaję -m python do shebangu, a jeśli uruchomię pdb.set_trace() w skrypcie.

Co tu się dzieje?

+2

Czy możesz zmienić skrypt, aby akceptował dane wejściowe z pliku innego niż stdin? – nmichaels

+0

możliwy duplikat testowania jednostki programowej Python CLI (http://stackoverflow.com/questions/13493288/python-cli-program-unit-testing) –

+1

@ user1901786 Jak uzyskać dostęp do wejścia standardowego w skrypcie CLI? Używając 'sys.stdin'? Czy chcesz napisać test na ten temat, czy też musisz uruchomić debugger w skrypcie? Jeśli potrzebujesz debuggera, w którym momencie chcesz go zaangażować? Niestety, pytanie jest dla mnie nieco niejasne. – famousgarkin

Odpowiedz

0

Kiedy używasz pdb (lub innego debuggera Pythona), uzyskuje on stdin dla poleceń debugowania, dlatego otrzymujesz NameError: name 'test' is not defined.

Na przykład ta komenda wyjdzie debugger na żebranie o czasie pracy i przyzwyczajenie się ten błąd (ani interaktywne debugowanie) na jednym cyklu:

(echo cd; echo „test”) | python -m pdb mytool.py

+2

Chociaż to wyjaśnia, co się dzieje, nie zapewnia odpowiedzi. – whereswalden

3

Możesz użyć innego deskryptora pliku. Z bash można utworzyć nowy deskryptor pliku z:

exec 3<> test.txt 

a następnie w pliku python mieć coś takiego:

#!/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) 

Wystarczy runiczny skrypt użyje tej Test.txt jako wejście, a ty może używać stdin na stdin. Może być również używany z rurami, jeśli potrzebujesz.

+3

Wolałbym rozwiązanie, które nie wymaga modyfikacji kodu narzędzia. – whereswalden

9

Inną opcją jest utworzenie własnego obiektu Pdb i ustawienie stdin i stdout. Mój dowód koncepcji obejmuje 2 terminale, ale na pewno niektóre prace mogą zostać połączone z pewnym niezabezpieczonym serwerem sieciowym.

  1. Utwórz dwa FIFO: mkfifo stdin mkfifo stdout

  2. W jednym terminalu otwartego stdout w tle, i pisać do standardowego wejścia: cat stdout & cat > stdin

  3. w kodzie Pythona/konsola tworzenia WPB obiektu, a użyj go: import pdb mypdb=pdb.Pdb(stdin=open('stdin','r'), stdout=open('stdout','w')) ... mypdb.set_trace() ...
  4. Zysk!

Powinieneś być w stanie używać pdb na pierwszej konsoli.

Jedyną wadą jest konieczność korzystania z niestandardowych WPB, ale niektóre małpy łatanie w init (PYTHONSTARTUP lub podobne) może pomóc:

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

0

Twój kontrolowania TTY jest nadal terminal, prawda? Użyj tego zamiast 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() 

Nie otrzymałem linii do autouzupełniania w tych okolicznościach. Strzałka w górę nie zadziała, ani żadna inna z linii czytelniczych readline.

Powiązane problemy