Utilisez-vous déjà print()
ou log()
pour déboguer votre code ? Bien sûr que oui. IceCream, ou ic
en abrégé, rend le débogage d'impression un peu plus agréable.
ic()
est comme print()
, mais en mieux :
IceCream est bien testé, sous licence permissive et prend en charge Python 3 et PyPy3.
IceCream recherche un contributeur principal + mainteneur. Aimeriez-vous diriger IceCream et améliorer le débogage pour tout le monde en Python ? N'hésitez pas à me contacter et à me le faire savoir ! ?
Avez-vous déjà imprimé des variables ou des expressions pour déboguer votre programme ? Si vous avez déjà tapé quelque chose comme
print ( foo ( '123' ))
ou le plus approfondi
print ( "foo('123')" , foo ( '123' ))
alors ic()
vous fera sourire. Avec les arguments, ic()
s'inspecte et imprime à la fois ses propres arguments et les valeurs de ces arguments.
from icecream import ic
def foo ( i ):
return i + 333
ic ( foo ( 123 ))
Impressions
ic| foo(123): 456
De la même manière,
d = { 'key' : { 1 : 'one' }}
ic ( d [ 'key' ][ 1 ])
class klass ():
attr = 'yep'
ic ( klass . attr )
Impressions
ic| d['key'][1]: 'one'
ic| klass.attr: 'yep'
Donnez simplement ic()
une variable ou une expression et vous avez terminé. Facile.
Avez-vous déjà utilisé print()
pour déterminer quelles parties de votre programme sont exécutées et dans quel ordre elles sont exécutées ? Par exemple, si vous avez déjà ajouté des instructions d'impression pour déboguer du code comme
def foo ():
print ( 0 )
first ()
if expression :
print ( 1 )
second ()
else :
print ( 2 )
third ()
alors ic()
aide ici aussi. Sans arguments, ic()
s'inspecte et imprime le nom du fichier appelant, le numéro de ligne et la fonction parent.
from icecream import ic
def foo ():
ic ()
first ()
if expression :
ic ()
second ()
else :
ic ()
third ()
Impressions
ic| example.py:4 in foo()
ic| example.py:11 in foo()
Appelez simplement ic()
et vous avez terminé. Simple.
ic()
renvoie son ou ses arguments, donc ic()
peut facilement être inséré dans du code préexistant.
>>> a = 6
>>> def half ( i ):
>>> return i / 2
>>> b = half(ic(a))
ic| a: 6
>>> ic(b)
ic| b: 3
ic.format(*args)
est comme ic()
mais la sortie est renvoyée sous forme de chaîne au lieu d'être écrite dans stderr.
>>> from icecream import ic
>>> s = ' sup '
>>> out = ic.format(s)
>>> print (out)
ic| s: 'sup'
De plus, la sortie de ic()
peut être entièrement désactivée, puis réactivée ultérieurement, respectivement avec ic.disable()
et ic.enable()
.
from icecream import ic
ic ( 1 )
ic . disable ()
ic ( 2 )
ic . enable ()
ic ( 3 )
Impressions
ic| 1: 1
ic| 3: 3
ic()
continue de renvoyer ses arguments lorsqu'il est désactivé, bien sûr ; aucun code existant avec des pauses ic()
.
Pour rendre ic()
disponible dans chaque fichier sans avoir besoin d'être importé dans chaque fichier, vous pouvez l' install()
. Par exemple, dans un A.py
racine :
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from icecream import install
install ()
from B import foo
foo ()
puis dans B.py
, qui est importé par A.py
, appelez simplement ic()
:
# -*- coding: utf-8 -*-
def foo ():
x = 3
ic ( x )
install()
ajoute ic()
au module intégré, qui est partagé entre tous les fichiers importés par l'interpréteur. De même, ic()
peut également être ultérieurement modifié par uninstall()
.
ic()
peut également être importé d'une manière qui échoue si IceCream n'est pas installé, comme dans les environnements de production (c'est-à-dire pas de développement). À cette fin, cet extrait d’importation de secours peut s’avérer utile :
try :
from icecream import ic
except ImportError : # Graceful fallback if IceCream isn't installed.
ic = lambda * a : None if not a else ( a [ 0 ] if len ( a ) == 1 else a ) # noqa
ic.configureOutput(prefix, outputFunction, argToStringFunction, includeContext, contextAbsPath)
contrôle la sortie de ic()
.
prefix
, s'il est fourni, adopte un préfixe de sortie personnalisé. prefix
peut être une chaîne, comme
>>> from icecream import ic
>>> ic.configureOutput( prefix = ' hello -> ' )
>>> ic( ' world ' )
hello -> 'world'
ou une fonction.
>>> import time
>>> from icecream import ic
>>>
>>> def unixTimestamp ():
>>> return ' %i |> ' % int (time.time())
>>>
>>> ic.configureOutput( prefix = unixTimestamp)
>>> ic( ' world ' )
1519185860 |> 'world': 'world'
La valeur par défaut du prefix
est ic|
.
outputFunction
, s'il est fourni, est appelé une fois pour chaque appel ic()
avec la sortie de ic()
, sous forme de chaîne, au lieu que cette chaîne soit écrite dans stderr (valeur par défaut).
>>> import logging
>>> from icecream import ic
>>>
>>> def warn ( s ):
>>> logging.warning(s)
>>>
>>> ic.configureOutput( outputFunction = warn)
>>> ic( ' eep ' )
WARNING:root:ic| 'eep': 'eep'
argToStringFunction
, s'il est fourni, est appelé avec des valeurs d'argument à sérialiser en chaînes affichables. La valeur par défaut est pprint.pformat() de PrettyPrint, mais elle peut être modifiée pour, par exemple, gérer les types de données non standard de manière personnalisée.
>>> from icecream import ic
>>>
>>> def toString ( obj ):
>>> if isinstance (obj, str ):
>>> return ' [!string %r with length %i !] ' % (obj, len (obj))
>>> return repr (obj)
>>>
>>> ic.configureOutput( argToStringFunction = toString)
>>> ic( 7 , ' hello ' )
ic| 7: 7, 'hello': [!string 'hello' with length 5!]
La argToStringFunction
par défaut est icecream.argumentToString
et dispose de méthodes pour register
et unregister
les fonctions à distribuer pour des classes spécifiques à l'aide functools.singledispatch
. Il dispose également d'une propriété registry
pour afficher les fonctions enregistrées.
>>> from icecream import ic, argumentToString
>>> import numpy as np
>>>
>>> # Register a function to summarize numpy array
>>> @ argumentToString.register(np.ndarray)
>>> def _ ( obj ):
>>> return f " ndarray, shape= { obj.shape } , dtype= { obj.dtype } "
>>>
>>> x = np.zeros(( 1 , 2 ))
>>> ic(x)
ic| x: ndarray, shape=(1, 2), dtype=float64
>>>
>>> # View registered functions
>>> argumentToString.registry
mappingproxy({object: <function icecream.icecream.argumentToString(obj)>,
numpy.ndarray: <function __main__._(obj)>})
>>>
>>> # Unregister a function and fallback to the default behavior
>>> argumentToString.unregister(np.ndarray)
>>> ic(x)
ic| x: array([[0., 0.]])
includeContext
, s'il est fourni et True, ajoute le nom de fichier, le numéro de ligne et la fonction parent de l'appel ic()
à la sortie de ic()
.
>>> from icecream import ic
>>> ic.configureOutput( includeContext = True )
>>>
>>> def foo ():
>>> i = 3
>>> ic(i)
>>> foo()
ic| example.py:12 in foo()- i: 3
includeContext
est False par défaut.
contextAbsPath
, s'il est fourni et True, génère des chemins de fichiers absolus, comme /path/to/foo.py
, sur uniquement les noms de fichiers, comme foo.py
, lorsque ic()
est appelé avec includeContext == True
. Ceci est utile lors du débogage de plusieurs fichiers partageant le(s) même(s) nom(s) de fichier. De plus, certains éditeurs, comme VSCode, transforment les chemins de fichiers absolus en liens cliquables qui ouvrent le fichier dans lequel ic()
a été appelé.
>>> from icecream import ic
>>> ic.configureOutput( includeContext = True , contextAbsPath = True )
>>>
>>> i = 3
>>>
>>> def foo ():
>>> ic(i)
>>> foo()
ic| /absolute/path/to/example.py:12 in foo()- i: 3
>>>
>>> ic.configureOutput( includeContext = True , contextAbsPath = False )
>>>
>>> def foo ():
>>> ic(i)
>>> foo()
ic| example.py:18 in foo()- i: 3
contextAbsPath
est False par défaut.
Installer IceCream avec pip est simple.
$ pip install icecream
ic()
utilise executing
par @alexmojaki pour localiser de manière fiable les appels ic()
dans la source Python. C'est magique.
De délicieuses glaces doivent être dégustées dans toutes les langues.
Si vous souhaitez une fonction ic()
similaire dans votre langue préférée, veuillez ouvrir une pull request ! L'objectif d'IceCream est d'améliorer le débogage d'impression avec une fonction ic()
très pratique dans chaque langue.