Você já usou print()
ou log()
para depurar seu código? Claro que sim. IceCream, ou ic
, abreviadamente, torna a depuração de impressão um pouco mais agradável.
ic()
é como print()
, mas melhor:
IceCream é bem testado, licenciado de forma permissiva e oferece suporte a Python 3 e PyPy3.
IceCream está procurando um contribuidor + mantenedor líder. Você adoraria liderar o IceCream e melhorar a depuração para todos em Python? Por favor, entre em contato e me avise! ?
Você já imprimiu variáveis ou expressões para depurar seu programa? Se você já digitou algo como
print ( foo ( '123' ))
ou o mais completo
print ( "foo('123')" , foo ( '123' ))
então ic()
colocará um sorriso em seu rosto. Com argumentos, ic()
inspeciona a si mesmo e imprime seus próprios argumentos e os valores desses argumentos.
from icecream import ic
def foo ( i ):
return i + 333
ic ( foo ( 123 ))
Impressões
ic| foo(123): 456
De forma similar,
d = { 'key' : { 1 : 'one' }}
ic ( d [ 'key' ][ 1 ])
class klass ():
attr = 'yep'
ic ( klass . attr )
Impressões
ic| d['key'][1]: 'one'
ic| klass.attr: 'yep'
Basta fornecer ic()
uma variável ou expressão e pronto. Fácil.
Você já usou print()
para determinar quais partes do seu programa são executadas e em que ordem são executadas? Por exemplo, se você já adicionou instruções de impressão para depurar código como
def foo ():
print ( 0 )
first ()
if expression :
print ( 1 )
second ()
else :
print ( 2 )
third ()
então ic()
ajuda aqui também. Sem argumentos, ic()
inspeciona a si mesmo e imprime o nome do arquivo de chamada, o número da linha e a função pai.
from icecream import ic
def foo ():
ic ()
first ()
if expression :
ic ()
second ()
else :
ic ()
third ()
Impressões
ic| example.py:4 in foo()
ic| example.py:11 in foo()
Basta chamar ic()
e pronto. Simples.
ic()
retorna seu(s) argumento(s), então ic()
pode ser facilmente inserido em código pré-existente.
>>> a = 6
>>> def half ( i ):
>>> return i / 2
>>> b = half(ic(a))
ic| a: 6
>>> ic(b)
ic| b: 3
ic.format(*args)
é como ic()
mas a saída é retornada como uma string em vez de escrita em stderr.
>>> from icecream import ic
>>> s = ' sup '
>>> out = ic.format(s)
>>> print (out)
ic| s: 'sup'
Além disso, a saída de ic()
pode ser totalmente desabilitada e posteriormente reativada, com ic.disable()
e ic.enable()
respectivamente.
from icecream import ic
ic ( 1 )
ic . disable ()
ic ( 2 )
ic . enable ()
ic ( 3 )
Impressões
ic| 1: 1
ic| 3: 3
ic()
continua retornando seus argumentos quando desativado, é claro; nenhum código existente com quebras ic()
.
Para disponibilizar ic()
em todos os arquivos sem precisar ser importado em todos os arquivos, você pode install()
. Por exemplo, em uma raiz A.py
:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from icecream import install
install ()
from B import foo
foo ()
e depois em B.py
, que é importado por A.py
, basta chamar ic()
:
# -*- coding: utf-8 -*-
def foo ():
x = 3
ic ( x )
install()
adiciona ic()
ao módulo interno, que é compartilhado entre todos os arquivos importados pelo interpretador. Da mesma forma, ic()
também pode ser editado posteriormente uninstall()
.
ic()
também pode ser importado de uma maneira que falha normalmente se o IceCream não estiver instalado, como em ambientes de produção (ou seja, não de desenvolvimento). Para esse fim, este snippet de importação substituto pode ser útil:
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)
controla a saída de ic()
.
prefix
, se fornecido, adota um prefixo de saída personalizado. prefix
pode ser uma string, como
>>> from icecream import ic
>>> ic.configureOutput( prefix = ' hello -> ' )
>>> ic( ' world ' )
hello -> 'world'
ou uma função.
>>> import time
>>> from icecream import ic
>>>
>>> def unixTimestamp ():
>>> return ' %i |> ' % int (time.time())
>>>
>>> ic.configureOutput( prefix = unixTimestamp)
>>> ic( ' world ' )
1519185860 |> 'world': 'world'
O valor padrão do prefix
é ic|
.
outputFunction
, se fornecido, é chamado uma vez para cada chamada de ic()
com a saída de ic()
, como uma string, em vez de essa string ser gravada em stderr (o padrão).
>>> import logging
>>> from icecream import ic
>>>
>>> def warn ( s ):
>>> logging.warning(s)
>>>
>>> ic.configureOutput( outputFunction = warn)
>>> ic( ' eep ' )
WARNING:root:ic| 'eep': 'eep'
argToStringFunction
, se fornecido, é chamado com valores de argumento a serem serializados em strings exibíveis. O padrão é pprint.pformat() do PrettyPrint, mas isso pode ser alterado para, por exemplo, lidar com tipos de dados não padrão de maneira personalizada.
>>> 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!]
O argToStringFunction
padrão é icecream.argumentToString
e possui métodos para register
e unregister
de funções a serem despachadas para classes específicas usando functools.singledispatch
. Ele também possui uma propriedade registry
para visualizar funções registradas.
>>> 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
, se fornecido e True, adiciona o nome do arquivo, o número da linha e a função pai da chamada ic()
à saída 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
é falso por padrão.
contextAbsPath
, se fornecido e True, gera caminhos de arquivos absolutos, como /path/to/foo.py
, apenas sobre nomes de arquivos, como foo.py
, quando ic()
é chamado com includeContext == True
. Isso é útil ao depurar vários arquivos que compartilham o(s) mesmo(s) nome(s) de arquivo. Além disso, alguns editores, como o VSCode, transformam caminhos de arquivos absolutos em links clicáveis que abrem o arquivo onde ic()
foi chamado.
>>> 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
é falso por padrão.
Instalar o IceCream com pip é fácil.
$ pip install icecream
ic()
usa executing
de @alexmojaki para localizar com segurança chamadas ic()
na fonte Python. É mágico.
Delicioso sorvete deve ser apreciado em todos os idiomas.
Se você quiser uma função ic()
semelhante em seu idioma favorito, abra uma solicitação pull! O objetivo do IceCream é adoçar a depuração de impressão com uma função ic()
útil em todas as linguagens.