2013-06-12 4 views
15

Я пытаюсь отлаживать CLI Python, я написал, что может принимать его аргументы от stdin. Простой тест будет иметь выходКак отлаживать CLI python, который принимает stdin?

echo "test" | python mytool.py 

быть эквивалентен выходом

python mytool.py test 

я хотел бы отладить некоторые проблемы с этим инструментом, поэтому я попытался запустить это:

echo "test" | pdb mytool.py 

Но я получаю этот выход, то PDB выходы:

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

То же самое происходит, когда я добавляю -m python в shebang, и если я запускаю pdb.set_trace() внутри скрипта.

Что здесь происходит?

+2

Можете изменить сценарий, чтобы принимать входные данные из файла, отличного от stdin? – nmichaels

+0

Возможный дубликат [Python CLI program unit testing] (http://stackoverflow.com/questions/13493288/python-cli-program-unit-testing) –

+1

@ user1901786 Как вы получаете доступ к stdin в скрипте CLI? Использование 'sys.stdin'? Кроме того, вы просто хотите написать тест для этого или вам нужно запустить отладчик в скрипте? Если вам нужен отладчик, в какой момент вы хотите, чтобы он задействовал сценарий? Извините, вопрос для меня немного неясен. – famousgarkin

ответ

0

Когда вы используете pdb (или любой другой отладчик python), он получает stdin для отладочных команд, поэтому вы получаете NameError: name 'test' is not defined.

Например, эта команда будет выйти из отладчика в попрошайничество среды выполнения, и вы не получите эту ошибку (ни интерактивной отладки) за один прогон:

(эхо продолжение, эхо «тест») | python -m pdb mytool.py

+2

Хотя это объясняет, что происходит, оно не дает ответа. – whereswalden

3

Вы можете использовать другой файловый дескриптор. С Башем вы можете создать новый дескриптор файла с:

exec 3<> test.txt 

а затем на файл питона есть что-то вроде:

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

Просто подножка вашего скрипта будет использовать этот test.txt в качестве входных данных, и вы может использовать stdin на stdin. Его также можно использовать с трубами, если вам нужно.

+3

Я бы предпочел решение, которое не требует изменения кода инструмента. – whereswalden

9

Другой вариант - создать собственный объект Pdb и установить там stdin и stdout. Мое доказательство концепции включает в себя 2 терминала, но наверняка некоторые работы могут быть объединены с каким-то очень незащищенным сетевым сервером.

  1. Создание два FIFOs: mkfifo stdin mkfifo stdout

  2. В одном терминале, открытый стандартный вывод на фоне и писать стандартный ввод: cat stdout & cat > stdin

  3. В коде Python/консоли создать PDB объект, и используйте его: import pdb mypdb=pdb.Pdb(stdin=open('stdin','r'), stdout=open('stdout','w')) ... mypdb.set_trace() ...
  4. Прибыль!

Вы должны иметь возможность использовать pdb на первой консоли.

Единственным недостатком является необходимость использовать пользовательские PDB, но некоторые обезьяны заплат при инициализации (PYTHONSTARTUP или аналогичный) могут помочь:

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

0

Ваш контроль TTY еще терминал, не так ли? Используйте это вместо 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() 

Не получили readline для автозаполнения в данных обстоятельствах. Стрелка вверх тоже не будет работать, или любая другая из тонкостей readline.

 Смежные вопросы

  • Нет связанных вопросов^_^