Как отлаживать CLI python, который принимает stdin?
Я пытаюсь отлаживать Python CLI, который я написал, который может принимать свои аргументы от 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()
внутри script.
Что здесь происходит?
Ответы
Ответ 1
Другой вариант - создать свой собственный объект Pdb и установить там stdin и stdout. Мое доказательство концепции включает в себя 2 терминала, но наверняка некоторые работы могут быть объединены с каким-то очень незащищенным сетевым сервером.
Вы должны иметь возможность использовать pdb на первой консоли.
Единственным недостатком является использование вашего пользовательского pdb, но некоторые исправления обезьян в init (PYTHONSTARTUP или аналогичные) могут помочь:
import pdb
mypdb=pdb.Pdb(stdin=open('stdin','r'), stdout=open('stdout','w'))
pdb.set_trace=mydbp.set_trace
Ответ 2
Вы можете использовать другой файловый дескриптор. С помощью bash вы можете создать новый файловый дескриптор с помощью:
exec 3<> test.txt
И тогда в вашем файле python есть что-то вроде:
#!/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)
Просто запуск вашего script будет использовать этот test.txt в качестве входных данных, и вы можете использовать stdin на stdin. Его также можно использовать с трубами, если вам нужно.
Ответ 3
Когда вы используете pdb (или любой другой отладчик python), он получает stdin
для команд отладки, поэтому вы получаете NameError: name 'test' is not defined
.
Например, эта команда закроет отладчик при запуске среды выполнения, и вы не получите эту ошибку (или интерактивную отладку) для одного запуска:
(echo cont; echo "test" ) | python -m pdb mytool.py
Ответ 4
Управляющий 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.