2009-12-24 6 views
5

Si j'ai un programme où stdout est redirigé, mes invites pdb tous vont à la redirection, car la bibliothèque a été écrite pour écrire à stdout.meilleure façon de faire face à python pdb flakiness re/stdout?

Souvent, ce problème est subtil, ce qui m'amène à penser qu'un programme est suspendu lorsqu'il attend vraiment l'entrée.

Comment les gens travaillent autour de cela? (Malheureusement, l'utilisation d'autres débogueurs comme winpdb n'est pas une option).

Répondre

2

le problème est ici qui utilise PDB classe Cmd où par défaut:

use_rawinput = 1 

Cela signifie que Cmd utilisera la méthode raw_input() par défaut au lieu de sys.stdout.readline() pour lire à partir de la console. Ceci est fait parce que raw_input() prend en charge l'historique (uniquement si le module readline est chargé) et d'autres bits utiles. Le seul problème est que raw_input() ne prend pas en charge la redirection, donc si vous avez un script:

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

et l'exécuter

> python test.py 
Enter your name: Alex 

mais, si vous l'exécutez avec la redirection de sortie, il sera bloqué

> python test.py | tee log 

C'est exactement ce que PDB utilise et pourquoi il est également bloqué. Comme je l'ai mentionné sys.stdin.readline() prend en charge la redirection et si vous réécrivez le script ci-dessus en utilisant readline() cela devrait fonctionner.

Retour à la question d'origine tout ce que vous devez faire est de dire Cmd de ne pas utiliser raw_input():

Cmd.use_rawinput = 0 

ou

pdb = pdb.Pdb() 
pdb.use_rawinput=0 
pdb.set_trace() 
2

Si vous appelez pdb dans le code, vous pouvez passer votre propre sortie standard dans le constructeur. sys.__stdout__ pourrait être un bon choix.

Si vous appelez pdb à partir de la ligne de commande, vous pouvez copier la fonction main() de pdb.py dans votre propre sane_pdb.py. Modifiez ensuite l'initialisation PDB():

pdb = Pdb(stdout=sys.__stdout__) 

Ensuite, vous pouvez invoquer sane_pdb.py au lieu de pdb.py. Ce n'est pas génial que vous deviez copier 40 lignes dans votre propre fichier juste pour en changer un, mais c'est une option.

4

Cette réponse est juste pour compléter Ned, comme un moyen d'envelopper la pdb.py fonction main() d'une manière qui ne nécessite pas la copie 40 lignes juste pour changer un d'entre eux:

# 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() 

Je don sais pas si cela fonctionne réellement pour le problème de l'interlocuteur, mais il fait ce que Ned décrit ...