Je débogue mes Python utilisant pdb et le manuel dit que je peux utiliser p variables commande pour imprimer les valeurs des variables spécifiées à un moment donné. Mais que se passe-t-il si j'ai beaucoup de variables, comme 20 variables, et que je souhaite suivre la valeur de chacune d'entre elles? Comment puis-je les imprimer toutes sans en spécifiant chaque élément manuellement? Prenez par exemple ce script:
a = 1
b = 2
c = 3
Je peux le déboguer avec pdb et les imprimer en utilisant p a, b, c comme ceci:
$ python -m pdb test.py
> /media/test.py(1)<module>()
-> a = 1
(Pdb) n
> /media/test.py(2)<module>()
-> b = 2
(Pdb) n
> /media/test.py(3)<module>()
(Pdb) n
--Return--
> /media/test.py(3)<module>()->None
-> c = 3
(Pdb) p a, b, c
(1, 2, 3)
(Pdb)
Mais je dois spécifier manuellement chaque variable. Existe-t-il un moyen d’imprimer toutes les variables en même temps, sans spécifier chacune d’elles?
pdb est un shell complet python, vous pouvez donc exécuter des commandes arbitraires.
locals()
et globals()
afficheront toutes les variables concernées par leurs valeurs.
Vous pouvez utiliser dir()
si les valeurs ne vous intéressent pas.
Lorsque vous déclarez une variable en Python, elle est placée dans les paramètres locaux ou globaux, le cas échéant, et il est impossible de distinguer une variable que vous avez définie et quelque chose qui se trouve dans votre étendue pour une autre raison.
Lorsque vous utilisez dir (), il est probable que les variables qui vous intéressent se trouvent au début ou à la fin de cette liste. Si vous voulez obtenir la clé, paires de valeur
Filtrer les sections locales () pourrait ressembler à quelque chose comme:
>>> x = 10
>>> y = 20
>>> {k: v for k,v in locals().iteritems() if '__' not in k and 'pdb' not in k}
{'y': 20, 'x': 10}
Si votre section locale () est un vrai désastre, vous aurez besoin de quelque chose d'un peu plus dur. Vous pouvez mettre la fonction suivante dans un module de votre pythonpath et l'importer pendant votre session de débogage.
def debug_Nice(locals_dict, keys=[]):
globals()['types'] = `__import__`('types')
exclude_keys = ['copyright', 'credits', 'False',
'True', 'None', 'Ellipsis', 'quit']
exclude_valuetypes = [types.BuiltinFunctionType,
types.BuiltinMethodType,
types.ModuleType,
types.TypeType,
types.FunctionType]
return {k: v for k,v in locals_dict.iteritems() if not
(k in keys or
k in exclude_keys or
type(v) in exclude_valuetypes) and
k[0] != '_'}
J'ai ajouté un exemple de session sur Pastebin
Il y a quelques cas que cela manque. Et vous voudrez peut-être l'étendre pour vous permettre de passer des types aussi. Mais cela devrait vous permettre de tout filtrer sauf les variables que vous avez définies.
dir ()
Si vous voulez juste les 20 dernières valeurs, vous obtenez une sortie comme >>> p var1 var2 ... varn
vous donnerait, alors vous feriez mieux de découper dir () comme dir () [- 20:], mais vous ne verrez pas facilement la relation entre les variables et les valeurs. Exemple: "Ai-je déclaré foo avant ou après le bar?"
Si vous voulez voir cette relation, vous pouvez essayer quelque chose comme ceci, qui suppose que vos variables sont à la fin de dir (). Vous pouvez trancher différemment s'ils sont au début. Cela ne fonctionnera pas bien si vos variables ne sont pas contiguës.
>>> Zip(dir(), [eval(var) for var in dir()])[-4:]
[('a', 10), ('var', 'var'), ('x', 30), ('y', 50)]
Comme indiqué dans cette liste pour plusieurs langues :
a = 1
b = 1
n = 'value'
#dir() == ['__builtins__', '__doc__', '__name__', '__package__', 'a', 'b', 'n']
for var in dir()[4:]:
value_of_var = eval(var)
print(value_of_var)
Sortie:
1
1
'value'
Etiqueter chacun est aussi simple que d’imprimer var + " equals " + eval(var)
.
Vous déclarez que votre "sortie idéale" correspond exactement au résultat obtenu en tapant p a, b, ... , n, ...
:
vars = []
for var in dir()[4:-1]
vars.append(var)
print(Tuple(vars))
La sortie ressemble à:
(1, 1, 'value')