лучший способ справиться с Python pdb flakiness re / stdout? - PullRequest
5 голосов
/ 24 декабря 2009

Если у меня есть программа, куда перенаправляется stdout, мои pdb-запросы все переходят в перенаправление, потому что библиотека была написана для записи в stdout.

Часто эта проблема неуловима, заставляя меня думать, что программа зависает, когда она действительно ожидает ввода.

Как люди обходят это? (К сожалению, использование других отладчиков, таких как winpdb, не вариант).

Ответы [ 3 ]

5 голосов
/ 25 декабря 2009

Этот ответ просто дополняет ответ Неда как способ обернуть функцию pdb.py main() способом, который не требует копирования 40 строк только для изменения одной из них:

# sane_pdb.py: launch Pdb with stdout on original
import sys, pdb
def fixed_pdb(Pdb=pdb.Pdb):
    '''make Pdb() tied to original stdout'''
    return Pdb(stdout=sys.__stdout__)

if __name__ == '__main__':
    pdb.Pdb = fixed_pdb
    pdb.main()

Я не знаю, действительно ли это работает для проблемы спрашивающего, но делает то, что описал Нед ...

3 голосов
/ 13 ноября 2014

Проблема здесь в том, что PDB использует класс Cmd, где по умолчанию:

use_rawinput = 1

Это означает, что Cmd будет использовать метод raw_input() по умолчанию вместо sys.stdout.readline() для чтения из консоли. Это сделано потому, что raw_input() поддерживает историю (только если загружен модуль readline) и другие полезные биты. Единственная проблема в том, что raw_input() не поддерживает перенаправление, поэтому, если у вас есть скрипт:

#!/usr/bin/python
name=raw_input("Enter your name: ")

и запустите

> python test.py
Enter your name: Alex

но, если вы запустите его с перенаправлением вывода, он застрянет

> python test.py | tee log

это именно то, что использует PDB, и почему он тоже застрял. Как я уже говорил, sys.stdin.readline() поддерживает перенаправление, и если вы переписываете скрипт выше, используя readline(), он должен работать.

Возвращаясь к исходной проблеме, все, что вам нужно сделать, это указать Cmd не использовать raw_input():

Cmd.use_rawinput = 0

или

pdb = pdb.Pdb()
pdb.use_rawinput=0
pdb.set_trace()
2 голосов
/ 25 декабря 2009

Если вы вызываете pdb в коде, вы можете передать свой собственный стандартный вывод в конструктор. sys.__stdout__ может быть хорошим выбором.

Если вы вызываете pdb из командной строки, вы можете скопировать функцию main() из pdb.py в свой собственный sane_pdb.py. Затем измените инициализацию Pdb () на:

pdb = Pdb(stdout=sys.__stdout__)

Тогда вы можете вызвать sane_pdb.py вместо pdb.py. Не удивительно, что вам нужно скопировать 40 строк в ваш собственный файл, чтобы просто изменить одну из них, но это вариант.

...