3. Debugging

3.1. Introdution

In this chapter, the ‘sys’ module is discussed to read the input from the terminal. Then a little overview of the debugging tool is provided, which will be used in subsequent chapters.

3.2. First code

In the below code, perimeter and area of a circular ring is calculated.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# ring.py

from math import pi

metal = "Copper"
radius = 10

perimeter = 2*pi*radius
area = pi * radius**2

print("Metal = ", metal)
print("pi = ", pi)
print("Perimeter = ", perimeter)
print("area = ", area)

Following is the output of the above code,

$ python ring.py
Metal =  Copper
pi =  3.141592653589793
Perimeter =  62.83185307179586
area =  314.1592653589793

3.3. Reading input from command line

In the previous code, the inputs, i.e. radius and metal, are hardwired in the code. In this section, we will modify the code, so that the inputs values can be provided from the termial.

  • For this, we need to import ‘sys’ module.

    Note

    • The ‘sys.argv’ pass the command line argument to Python script.
    • The argv[0] is the file name.
    • Also, the arguments are passed as string-format, therefore these need to be converted into proper format, as done in Line 16, where the argv[2] is converted into ‘float’ format.
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    # ring.py
    
    import sys
    
    from math import pi
    
    if len(sys.argv) != 3:  # display error message for missing arguments
        raise SystemExit("usage : ring.py \"metal\" radius")
    
    # sys.argv[0] is the file name
    # metal = "Copper"
    metal = sys.argv[1]
    
    # radius = 10
    # input is read as string therefore it is converted into float
    radius = float(sys.argv[2])
    
    perimeter = 2*pi*radius
    area = pi * radius**2
    
    print("Metal =", metal)
    # print("pi =", pi)
    print("Perimeter =", perimeter)
    print("area =", area)
    
  • Now, run the command and we will get the following outputs.

    $ python ring.py
    usage : ring.py "metal" radius
    
    $ python ring.py "Gold" 2
    Metal = Gold
    Perimeter = 12.566370614359172
    area = 12.566370614359172
    

3.4. Debugging

In this section, two basic methods are shown for debugging the code. In the later chapters, we will see use some advance topics such as decorator and descriptor etc. to debug the design.

3.4.1. Run script and go to Python shell

One of the way to debug the code is to use Python shell. For this we can use the ‘-i’ option as shown below. After executing of the code using ‘i’ option, the Python shell will be open, where we can check the various values or behavior of the implemented logics. We will use this method extensively in the tutorial.

$ python -i ring.py "Gold" 2
Metal = Gold
Perimeter = 12.566370614359172
area = 12.566370614359172
>>> print(sys.argv) # print the arguments read from terminal
['ring.py', 'Gold', '2']
>>> print(metal)
Gold

3.4.2. Python debugger (pdb)

Another way to debug the code is to use the ‘pdb’, as shown below,

  • Here, python debugger module is imported at Line 3.

  • Next, pdb.set_trace is used to set the starting location for the debugging, i.e. the code will stop after reaching this point i.e. Line 15 here.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    # ring.py
    
    import pdb # Python Debugger
    import sys
    
    from math import pi
    
    if len(sys.argv) != 3: # display error message for missing arguments
        raise SystemExit("usage : ring.py \"metal\" radius")
    
    # print arguments
    print("Entered values: ", sys.argv)
    
    # manual debugging starts from here
    pdb.set_trace()
    
    # sys.argv[0] is the file name
    # metal = "Copper"
    metal = sys.argv[1]
    
    # radius = 10
    # input is read as string therefore it is converted into float
    radius = float(sys.argv[2])
    
    perimeter = 2*pi*radius
    area = pi * radius**2
    
    print("Metal =", metal)
    # print("pi =", pi)
    print("Perimeter =", perimeter)
    print("area =", area)
    
  • Now, run the code as below. Press ‘s’ and then enter to execute the next line.

    $ python ring.py "Gold" 2
    Entered values:  ['ring.py', 'Gold', '2']
    > /ring.py(19)<module>()
    -> metal = sys.argv[1]
    (Pdb) s
    > /ring.py(23)<module>()
    -> radius = float(sys.argv[2])
    

3.5. Underscore operator (_)

The Underscore operator stores the last value of the calculation and can be very useful while debugging the code in Python shell.

>>> 3 + 2
5
>>> _ * 2
10

3.6. Conclusion

In this chapter, we saw the debugging tools which will be used in subsequent chapters. Also, the module ‘sys’ is discussed for reading the inputs from the terminal.