Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/gruns/icecream
๐ฆ Never use print() to debug again.
https://github.com/gruns/icecream
debug debugging debugging-tool inspects library print python python3
Last synced: 4 days ago
JSON representation
๐ฆ Never use print() to debug again.
- Host: GitHub
- URL: https://github.com/gruns/icecream
- Owner: gruns
- License: mit
- Created: 2018-02-13T18:56:12.000Z (almost 7 years ago)
- Default Branch: master
- Last Pushed: 2024-11-28T09:28:07.000Z (about 2 months ago)
- Last Synced: 2025-01-06T16:03:55.007Z (6 days ago)
- Topics: debug, debugging, debugging-tool, inspects, library, print, python, python3
- Language: Python
- Homepage:
- Size: 390 KB
- Stars: 9,401
- Watchers: 52
- Forks: 194
- Open Issues: 85
-
Metadata Files:
- Readme: README.md
- Changelog: changelog.txt
- License: LICENSE.txt
Awesome Lists containing this project
- awesome-python-resources - GitHub - 26% open ยท โฑ๏ธ 21.07.2022): (่ฐ่ฏๅทฅๅ ท)
- best-of-python-dev - GitHub - 52% open ยท โฑ๏ธ 01.02.2024): (Debugging Tools)
- starred-awesome - icecream - ๐ฆ Sweet and creamy print debugging. (Python)
- StarryDivineSky - gruns/icecream
README
### IceCream โ Never use print() to debug again
Do you ever use `print()` or `log()` to debug your code? Of course you
do. IceCream, or `ic` for short, makes print debugging a little sweeter.`ic()` is like `print()`, but better:
1. It prints both variables and expressions along with their values.
2. It's 60% faster to type.
3. Data structures are formatted and pretty printed.
4. Output is syntax highlighted.
5. It optionally includes program context: filename, line number, and
parent function.IceCream is well tested, [permissively licensed](LICENSE.txt), and supports Python 3 and PyPy3.
๐ฅ IceCream is looking for a lead contributor + maintainer. Would you
love to lead IceCream and improve debugging for everyone in Python?
Please [reach out]([email protected]) and let me know! ๐### Inspect Variables
Have you ever printed variables or expressions to debug your program? If
you've ever typed something like```python
print(foo('123'))
```or the more thorough
```python
print("foo('123')", foo('123'))
```then `ic()` will put a smile on your face. With arguments, `ic()`
inspects itself and prints both its own arguments and the values of
those arguments.```python
from icecream import icdef foo(i):
return i + 333ic(foo(123))
```Prints
```
ic| foo(123): 456
```Similarly,
```python
d = {'key': {1: 'one'}}
ic(d['key'][1])class klass():
attr = 'yep'
ic(klass.attr)
```Prints
```
ic| d['key'][1]: 'one'
ic| klass.attr: 'yep'
```Just give `ic()` a variable or expression and you're done. Easy.
### Inspect Execution
Have you ever used `print()` to determine which parts of your program are
executed, and in which order they're executed? For example, if you've ever added
print statements to debug code like```python
def foo():
print(0)
first()if expression:
print(1)
second()
else:
print(2)
third()
```then `ic()` helps here, too. Without arguments, `ic()` inspects itself and
prints the calling filename, line number, and parent function.```python
from icecream import icdef foo():
ic()
first()if expression:
ic()
second()
else:
ic()
third()
```Prints
```
ic| example.py:4 in foo()
ic| example.py:11 in foo()
```Just call `ic()` and you're done. Simple.
### Return Value
`ic()` returns its argument(s), so `ic()` can easily be inserted into
pre-existing code.```pycon
>>> a = 6
>>> def half(i):
>>> return i / 2
>>> b = half(ic(a))
ic| a: 6
>>> ic(b)
ic| b: 3
```### Miscellaneous
`ic.format(*args)` is like `ic()` but the output is returned as a string instead
of written to stderr.```pycon
>>> from icecream import ic
>>> s = 'sup'
>>> out = ic.format(s)
>>> print(out)
ic| s: 'sup'
```Additionally, `ic()`'s output can be entirely disabled, and later re-enabled, with
`ic.disable()` and `ic.enable()` respectively.```python
from icecream import icic(1)
ic.disable()
ic(2)ic.enable()
ic(3)
```Prints
```
ic| 1: 1
ic| 3: 3
````ic()` continues to return its arguments when disabled, of course; no existing
code with `ic()` breaks.### Import Tricks
To make `ic()` available in every file without needing to be imported in
every file, you can `install()` it. For example, in a root `A.py`:```python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-from icecream import install
install()from B import foo
foo()
```and then in `B.py`, which is imported by `A.py`, just call `ic()`:
```python
# -*- coding: utf-8 -*-def foo():
x = 3
ic(x)
````install()` adds `ic()` to the
[builtins](https://docs.python.org/3.8/library/builtins.html) module,
which is shared amongst all files imported by the interpreter.
Similarly, `ic()` can later be `uninstall()`ed, too.`ic()` can also be imported in a manner that fails gracefully if
IceCream isn't installed, like in production environments (i.e. not
development). To that end, this fallback import snippet may prove
useful:```python
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
```### Configuration
`ic.configureOutput(prefix, outputFunction, argToStringFunction,
includeContext, contextAbsPath)` controls `ic()`'s output.`prefix`, if provided, adopts a custom output prefix. `prefix` can be a
string, like```pycon
>>> from icecream import ic
>>> ic.configureOutput(prefix='hello -> ')
>>> ic('world')
hello -> 'world'
```or a function.
```pycon
>>> import time
>>> from icecream import ic
>>>
>>> def unixTimestamp():
>>> return '%i |> ' % int(time.time())
>>>
>>> ic.configureOutput(prefix=unixTimestamp)
>>> ic('world')
1519185860 |> 'world': 'world'
````prefix`'s default value is `ic| `.
`outputFunction`, if provided, is called once for every `ic()` call with
`ic()`'s output, as a string, instead of that string being written to
stderr (the default).```pycon
>>> import logging
>>> from icecream import ic
>>>
>>> def warn(s):
>>> logging.warning(s)
>>>
>>> ic.configureOutput(outputFunction=warn)
>>> ic('eep')
WARNING:root:ic| 'eep': 'eep'
````argToStringFunction`, if provided, is called with argument values to be
serialized to displayable strings. The default is PrettyPrint's
[pprint.pformat()](https://docs.python.org/3/library/pprint.html#pprint.pformat),
but this can be changed to, for example, handle non-standard datatypes
in a custom fashion.```pycon
>>> 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!]
```The default `argToStringFunction` is `icecream.argumentToString`, and
has methods to `register` and `unregister` functions to be dispatched
for specific classes using `functools.singledispatch`. It also has a
`registry` property to view registered functions.```pycon
>>> 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: ,
numpy.ndarray: })
>>>
>>> # Unregister a function and fallback to the default behavior
>>> argumentToString.unregister(np.ndarray)
>>> ic(x)
ic| x: array([[0., 0.]])
````includeContext`, if provided and True, adds the `ic()` call's filename,
line number, and parent function to `ic()`'s output.```pycon
>>> from icecream import ic
>>> ic.configureOutput(includeContext=True)
>>>
>>> def foo():
>>> i = 3
>>> ic(i)
>>> foo()
ic| example.py:12 in foo()- i: 3
````includeContext` is False by default.
`contextAbsPath`, if provided and True, outputs absolute filepaths, like
`/path/to/foo.py`, over just filenames, like `foo.py`, when `ic()` is
called with `includeContext == True`. This is useful when debugging
multiple files that share the same filename(s). Moreover, some editors,
like VSCode, turn absolute filepaths into clickable links that open the
file where `ic()` was called.```pycon
>>> 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` is False by default.
### Installation
Installing IceCream with pip is easy.
```
$ pip install icecream
```### Related Python libraries
`ic()` uses [**`executing`**](https://github.com/alexmojaki/executing)
by [**@alexmojaki**](https://github.com/alexmojaki) to reliably locate
`ic()` calls in Python source. It's magic.### IceCream in Other Languages
Delicious IceCream should be enjoyed in every language.
- Dart: [icecream](https://github.com/HallerPatrick/icecream)
- Rust: [icecream-rs](https://github.com/ericchang00/icecream-rs)
- Node.js: [node-icecream](https://github.com/jmerle/node-icecream)
- C++: [IceCream-Cpp](https://github.com/renatoGarcia/icecream-cpp)
- C99: [icecream-c](https://github.com/chunqian/icecream-c)
- PHP: [icecream-php](https://github.com/ntzm/icecream-php)
- Go: [icecream-go](https://github.com/WAY29/icecream-go)
- Ruby: [Ricecream](https://github.com/nodai2hITC/ricecream)
- Java: [icecream-java](https://github.com/Akshay-Thakare/icecream-java)
- R: [icecream](https://github.com/lewinfox/icecream)
- Lua: [icecream-lua](https://github.com/wlingze/icecream-lua)
- Clojure(Script): [icecream-cljc](https://github.com/Eigenbahn/icecream-cljc)
- Bash: [IceCream-Bash](https://github.com/jtplaarj/IceCream-Bash)
- SystemVerilog: [icecream_sv](https://github.com/xver/icecream_sv)If you'd like a similar `ic()` function in your favorite language, please open a
pull request! IceCream's goal is to sweeten print debugging with a handy-dandy
`ic()` function in every language.