Вы когда-нибудь использовали print()
или log()
для отладки кода? Конечно, да. IceCream, или сокращенно ic
, делает отладку печати немного приятнее.
ic()
похож на print()
, но лучше:
IceCream хорошо протестирован, имеет разрешительную лицензию и поддерживает Python 3 и PyPy3.
IceCream ищет ведущего участника и сопровождающего. Хотели бы вы возглавить IceCream и улучшить отладку для всех на Python? Пожалуйста, свяжитесь со мной и дайте мне знать! ?
Вы когда-нибудь выводили переменные или выражения для отладки вашей программы? Если вы когда-нибудь печатали что-то вроде
print ( foo ( '123' ))
или более тщательный
print ( "foo('123')" , foo ( '123' ))
тогда ic()
вызовет улыбку на вашем лице. Что касается аргументов, ic()
проверяет себя и печатает как свои собственные аргументы, так и значения этих аргументов.
from icecream import ic
def foo ( i ):
return i + 333
ic ( foo ( 123 ))
Принты
ic| foo(123): 456
Сходным образом,
d = { 'key' : { 1 : 'one' }}
ic ( d [ 'key' ][ 1 ])
class klass ():
attr = 'yep'
ic ( klass . attr )
Принты
ic| d['key'][1]: 'one'
ic| klass.attr: 'yep'
Просто задайте ic()
переменную или выражение, и все готово. Легкий.
Вы когда-нибудь использовали print()
чтобы определить, какие части вашей программы выполняются и в каком порядке? Например, если вы когда-либо добавляли операторы печати в код отладки, например
def foo ():
print ( 0 )
first ()
if expression :
print ( 1 )
second ()
else :
print ( 2 )
third ()
тогда ic()
поможет и здесь. Без аргументов ic()
проверяет себя и печатает имя вызывающего файла, номер строки и родительскую функцию.
from icecream import ic
def foo ():
ic ()
first ()
if expression :
ic ()
second ()
else :
ic ()
third ()
Принты
ic| example.py:4 in foo()
ic| example.py:11 in foo()
Просто вызовите ic()
и все готово. Простой.
ic()
возвращает свои аргументы, поэтому ic()
можно легко вставить в уже существующий код.
>>> a = 6
>>> def half ( i ):
>>> return i / 2
>>> b = half(ic(a))
ic| a: 6
>>> ic(b)
ic| b: 3
ic.format(*args)
похож на ic()
, но выходные данные возвращаются в виде строки, а не записываются в поток stderr.
>>> from icecream import ic
>>> s = ' sup '
>>> out = ic.format(s)
>>> print (out)
ic| s: 'sup'
Кроме того, вывод ic()
можно полностью отключить, а затем снова включить с помощью ic.disable()
и ic.enable()
соответственно.
from icecream import ic
ic ( 1 )
ic . disable ()
ic ( 2 )
ic . enable ()
ic ( 3 )
Принты
ic| 1: 1
ic| 3: 3
Разумеется, ic()
продолжает возвращать свои аргументы даже после отключения; никакой существующий код с прерываниями ic()
.
Чтобы сделать ic()
доступным в каждом файле без необходимости импорта в каждый файл, вы можете install()
его. Например, в корне A.py
:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from icecream import install
install ()
from B import foo
foo ()
а затем в B.py
, который импортируется A.py
, просто вызовите ic()
:
# -*- coding: utf-8 -*-
def foo ():
x = 3
ic ( x )
install()
добавляет ic()
во встроенный модуль, который используется всеми файлами, импортируемыми интерпретатором. Аналогичным образом, позже можно также изменить uninstall()
ic()
.
ic()
также можно импортировать таким образом, что он не будет корректно работать, если IceCream не установлен, например, в производственных средах (т. е. не в разработке). В связи с этим может оказаться полезным этот резервный фрагмент импорта:
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)
управляет выводом ic()
.
prefix
, если он указан, принимает собственный префикс вывода. prefix
может быть строкой, например
>>> from icecream import ic
>>> ic.configureOutput( prefix = ' hello -> ' )
>>> ic( ' world ' )
hello -> 'world'
или функция.
>>> import time
>>> from icecream import ic
>>>
>>> def unixTimestamp ():
>>> return ' %i |> ' % int (time.time())
>>>
>>> ic.configureOutput( prefix = unixTimestamp)
>>> ic( ' world ' )
1519185860 |> 'world': 'world'
значение prefix
по умолчанию — ic|
.
outputFunction
, если он предусмотрен, вызывается один раз для каждого вызова ic()
с выводом ic()
в виде строки, вместо того, чтобы эта строка записывалась в stderr (по умолчанию).
>>> import logging
>>> from icecream import ic
>>>
>>> def warn ( s ):
>>> logging.warning(s)
>>>
>>> ic.configureOutput( outputFunction = warn)
>>> ic( ' eep ' )
WARNING:root:ic| 'eep': 'eep'
argToStringFunction
, если он указан, вызывается со значениями аргументов, которые будут сериализованы в отображаемые строки. По умолчанию используется pprint.pformat() из PrettyPrint, но его можно изменить, например, для обработки нестандартных типов данных собственным способом.
>>> 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!]
argToStringFunction
по умолчанию — icecream.argumentToString
и имеет методы для register
и unregister
функций, которые будут отправлены для определенных классов с помощью functools.singledispatch
. Он также имеет свойство registry
для просмотра зарегистрированных функций.
>>> 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
, если он указан и имеет значение True, добавляет имя файла, номер строки и родительскую функцию вызова ic()
к выводу 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
имеет значение False.
contextAbsPath
, если он указан и имеет значение True, выводит абсолютные пути к файлам, например /path/to/foo.py
, а не только имена файлов, например foo.py
, когда ic()
вызывается с includeContext == True
. Это полезно при отладке нескольких файлов с одинаковыми именами файлов. Более того, некоторые редакторы, такие как VSCode, превращают абсолютные пути к файлам в кликабельные ссылки, которые открывают файл, в котором была вызвана ic()
.
>>> 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
по умолчанию имеет значение False.
Установить IceCream с помощью pip очень просто.
$ pip install icecream
ic()
использует executing
@alexmojaki для надежного обнаружения вызовов ic()
в исходном коде Python. Это волшебство.
Вкусным мороженым нужно наслаждаться на любом языке.
Если вам нужна аналогичная функция ic()
на вашем любимом языке, откройте запрос на включение! Цель IceCream — облегчить отладку печати с помощью удобной функции ic()
на каждом языке.