Do you often use Python print() to debug your code? However, if you want to make a significant improvement, you could use IceCream which would make debugging faster, cleaner, and easier to read. ic(), which is short for IceCream prints both expressions/variable names and their values. ic() is faster to type than print(). The output is highlighted and printed in a structured format. If you want, you can include program context (filename, line number, and parent function) easily. You could effortlessly debug while solving competitive code problems and save a lot of time while debugging.
Installation
To install the IceCream module, you need to open up your terminal or command prompt and type the following command:
$ pip install icecream
After installing the IceCream module, we are ready to use IceCream to debug Python code efficiently.
Why use IceCream to debug
Let’s look at an example where the average of three values is printed by the Python code.
Note: This is just an example, so just concentrate where and for which variable the print() function is used rather than understanding the code.
Python3
# Python program to print average of three values a = 3 b = 11 c = 42 for i in range ( 80 , 83 ): a = a * i b = b * i c = c * i ans = (a + b + c) / 3 print (a) print (b) print (c) print ( int (ans)) |
Output:
$ python gfg.py 240 880 3360 1493 19440 71280 272160 120960 1594080 5844960 22317120 9918720
When we print the values of a, b, c and ans for debugging purposes, it is difficult to identify which variable corresponds to which output. But what if there are hundreds of values in the output? IceCream is very helpful in these situations for debugging.
Below is the code for printing a, b, c, and ans using IceCream ic().
Note: This is just an example, so just concentrate where and for which variable the ic() function is used rather than understanding the code.
Python program to print average of three values using ic()
Python3
from icecream import ic a = 3 b = 11 c = 42 for i in range ( 80 , 83 ): a = a * i b = b * i c = c * i ans = (ic(a) + ic(b) + ic(c)) / 3 ic( int (ans)) |
Output:
$ python gfg.py ic| a: 240 ic| b: 880 ic| c: 3360 ic| int(ans): 1493 ic| a: 19440 ic| b: 71280 ic| c: 272160 ic| int(ans): 120960 ic| a: 1594080 ic| b: 5844960 ic| c: 22317120 ic| int(ans): 9918720
Explanation: Here, ic() is used between the code to print out the values in a structured and simpler method. We are easily able to identify the values of a, b, c and ans in the output.
Simplest Example
Here’s a basic example of how to use the IceCream ic() function. Any data type and data structure that python print() supports can be used with IceCream ic().
Python3
# Python program to print different # types of datatypes # and data structures using ic() from icecream import ic NUMBER = 2008 FLOAT = 95.47 BOOLEAN = True STRING = "GFG" LIST = [ 1 , 2 , 3 , 4 , 5 ] DICT = { "gfg" : "neveropen" , "founder" : "Sandeep Jain" , } ic( 123 ) ic(NUMBER) ic( FLOAT ) ic(BOOLEAN) ic(STRING) ic( LIST ) ic( DICT ) |
Output
ic| 123
ic| NUMBER: 2008
ic| FLOAT: 95.47
ic| BOOLEAN: True
ic| STRING: ‘GFG’
ic| LIST: [1, 2, 3, 4, 5]
ic| DICT: {‘founder’: ‘Sandeep Jain’, ‘gfg’: ‘neveropen’}
Invoking Python Function using icecream module ic()
Here’s an example to use IceCream with the python function. The implementation of ic() for printing the return value of the function is the same as using the python print function.
Python3
# Python program to implement ic() # on functions from icecream import ic def square(i): return i * i ic(square( 4 )) |
Output:
$ python gfg.py ic| square(4): 16
Explanation: Here, ic() prints the function with the argument that is being passed and the return value on the right.
Multiple ways to print ic() in a function
Here are a few different approaches to include ic() in a function to get basically the same result.
Python3
# Python program to understand different # ways to print using ic() from icecream import ic def multiply1(i, j, k): ic(i) ic(j) ic(k) return i * j * k def multiply2(i, j, k): ic(i, j, k) return i * j * k def multiply3(i, j, k): return ic(i) * ic(j) * ic(k) ic(multiply1( 1 , 2 , 3 )) ic(multiply2( 1 , 2 , 3 )) ic(multiply3( 1 , 2 , 3 )) |
Output:
$ python gfg.py ic| i: 1 ic| j: 2 ic| k: 3 ic| multiply1(1, 2, 3): 6 ic| i: 1, j: 2, k: 3 ic| multiply2(1, 2, 3): 6 ic| i: 1 ic| j: 2 ic| k: 3 ic| multiply3(1, 2, 3): 6
ic() helps in identifying the block of code that was executed
To determine which block of code was executed, you could use ic() to print the line that was executed. If no arguments are passed in ic(), it will print the line of code that was executed with the parent function, filename and time.
Python3
# Python program to print parent # function, filename, # and the line number as prefix from icecream import ic def gfg(value): ic() if value = = True : ic() return "GFG" else : ic() return - 1 ic(gfg( True )) |
Output:
$ python gfg.py ic| new.py:6 in gfg() at 18:42:14.916 ic| new.py:8 in gfg() at 18:42:14.917 ic| gfg(True): 'GFG'
Explanation: In the output, Line 1, 6 in gfg() indicates that the program executes the gfg() function and encounters ic() on line 6. Line 2, 8 in gfg() indicates that the program executes the if block and not the else block, as the argument value is passed ‘True’ and encounters ic() on the 8th line of the code. It also prints the time beside it.
ic() default configuration to print the filename, line number, and time as a prefix is false when an argument is passed. But it can be enabled by configuring the output, which we will learn next.
Using includeContext of icecream module
By configuring output as includeContext = True, the output will also print the parent function, filename, and the line number of the ic() which is executed.
Python3
# Python program to configure # prefix as parent function, # filename, and the line number from icecream import ic ic.configureOutput(includeContext = True ) def square(i): return ic(i) * i NUMBER = 2008 ic(NUMBER) ic(square( 23 )) |
Output:
$ python gfg.py" ic| 9.py:11 in <module>- NUMBER: 2008 ic| 9.py:7 in square()- i: 23 ic| 9.py:12 in <module>- square(23): 529
Enable/Disable icecream module
With ic.disable() and ic.enable(), respectively, the output of ic() can be completely turned off and then turned back on.
Python3
# Python program to enable/disable ic() from icecream import ic ic.disable() ic( 1990 ) ic( "Hello World" ) ic.enable() ic( "GFG" ) ic( 2008 ) |
Output:
$ python gfg.py ic| 'GFG' ic| 2008
Note: Here lines ic(1990) and ic(“Hello World”) are not getting printed.
Using configureOutput parameter in icecream module
IceCream module also enables you to configure a custom prefix. In the below example, we are going to learn how to configure the output prefix as time using a function.
Python3
# Python program to configure # output prefix as time from datetime import datetime from icecream import ic import time ic( "gfg" ) ic.configureOutput(prefix = "GFG " ) ic( "gfg" ) def time_format(): now = datetime.now() return f '{now.strftime("%H:%M:%S")} --> ' ic.configureOutput(prefix = time_format) for i in range ( 1 , 6 ): time.sleep( 1 ) ic(i) |
Output:
$ python gfg.py ic| 'gfg' GFG 'gfg' 02:02:41 --> i: 1 02:02:42 --> i: 2 02:02:43 --> i: 3 02:02:44 --> i: 4 02:02:45 --> i: 5
Explanation: In the output, line 1 shows the default output. Line 2 has a prefix ‘GFG’ which was configured in the code. From the 3rd line onwards, we were able to configure output with prefix time. The time shows a delay of 1 second as time.sleep() delays it as shown in the code. Finally, remove all the ic() after the debugging is complete.