End interactive session 2C
Objective:
This session aims to help you understand how to interpret error messages in Python. By generating errors in a controlled environment, youโll learn how to read error reports, identify the source of the problem, and correct your code. This is an essential skill for debugging and improving your Python programming abilities.
Part 1: Introduction to Python Errors
1.1 Generating a Syntax Error
In Python, a syntax error occurs when the code you write doesnโt conform to the rules of the language.
Step 1: Run the following code in a Jupyter notebook cell to generate a syntax error.
print("Hello WorldStep 2: Observe the error message. It should look something like this:
File "<ipython-input-1>", line 1 print("Hello World ^ SyntaxError: EOL while scanning string literalStep 3: Explanation: The error message indicates that the End Of Line (EOL) was reached while the string literal was still open. A string literal is what is created inside the open
"and close". The caret (^) points to where Python expected the closing quote.Step 4: Fix the Error: Correct the code by adding the missing closing quotation mark.
print("Hello World")
Part 2: Name Errors with Variables
2.1 Using an Undefined Variable
A NameError occurs when you try to use a variable that hasnโt been defined.
Step 1: Run the following code to generate a
NameError.print(variable)Step 2: Observe the error message.
NameError: name 'variable' is not definedStep 3: Explanation: Python is telling you that the variable
variablehas not been defined. This means you are trying to use a variable that Python doesnโt recognize.Step 4: Fix the Error: Define the variable before using it.
variable = "I'm now defined!" print(variable)
NameError patterns in Python
A NameError often occurs when Python canโt find a variable or function youโre trying to use. This is usually because of:
- Typos in Function or Variable Names:
If you mistype a function or variable name, Python will raise a
NameErrorbecause it doesnโt recognize the name.Example:
prnt("Hello, World!") # NameError: name 'prnt' is not defined- Fix: Correct the typo to
print("Hello, World!").
- Fix: Correct the typo to
- Using Literals as Variables:
A
NameErrorcan also happen if you accidentally try to use a string or number as if it were a variable.Example:
"Hello" = 5 # NameError: can't assign to literal- Fix: Make sure youโre using valid variable names and not trying to assign values to literals.
Remember: Always double-check your spelling and ensure that youโre using variable names correctly!
Part 3: Type Errors with Functions
3.1 Passing Incorrect Data Types
A TypeError occurs when an operation or function is applied to an object of an inappropriate type.
Step 1: Run the following code to generate a
TypeError.number = 5 print(number + "10")Step 2: Observe the error message.
TypeError: unsupported operand type(s) for +: 'int' and 'str'Step 3: Explanation: The error indicates that you are trying to add an integer (
int) and a string (str), which is not allowed in Python.Step 4: Fix the Error: Convert the string
"10"to an integer or the integernumberto a string.print(number + 10) # Correct approach 1 # or print(str(number) + "10") # Correct approach 2
Part 4: Index Errors with Lists
4.1 Accessing an Invalid Index
An IndexError occurs when you try to access an index that is out of the range of a list.
Step 1: Run the following code to generate an
IndexError.my_list = [1, 2, 3] print(my_list[5])Step 2: Observe the error message.
IndexError: list index out of rangeStep 3: Explanation: Python is telling you that the index
5is out of range for the listmy_list, which only has indices0, 1, 2.Step 4: Fix the Error: Access a valid index or use dynamic methods to avoid hardcoding indices.
print(my_list[2]) # Last valid index # or print(my_list[-1]) # Access the last element using negative indexing
Part 5: Attribute Errors
5.1 Using Attributes Incorrectly
An AttributeError occurs when you try to access an attribute or method that doesnโt exist on the object.
Step 1: Run the following code to generate an
AttributeError.my_string = "Hello" my_string.append(" World")Step 2: Observe the error message.
AttributeError: 'str' object has no attribute 'append'Step 3: Explanation: Python is telling you that the
strobject (a string) does not have anappendmethod, which is a method for lists.Step 4: Fix the Error: Use string concatenation instead of
append.my_string = "Hello" my_string = my_string + " World" print(my_string)
Part 6: Tracing Errors Through a Function Call Stack
6.1 Understanding a Complicated Error Stack Trace
Errors can sometimes appear deep within a function call, triggered by code that was written earlier in your script. When this happens, understanding the stack trace (the sequence of function calls leading to the error) is crucial for identifying the root cause. In this part of the exercise, youโll explore an example where an error in a plotting function arises from an earlier mistake in your code.
- Step 1: Run the following code, which attempts to plot a simple line graph using Matplotlib.
import matplotlib.pyplot as plt
def generate_plot(data):
plt.plot(data)
plt.show()
# Step 2: Introduce an error
my_data = [1, 2, "three", 4, 5] # Mixing strings and integers in the list
# Step 3: Call the function to generate the plot
generate_plot(my_data)- Step 2: Observe the error message.
File "<ipython-input-1>", line 5, in generate_plot
plt.plot(data)
...
File "/path/to/matplotlib/lines.py", line XYZ, in _xy_from_xy
raise ValueError("some explanation about incompatible types")
ValueError: could not convert string to float: 'three'
Step 3: Explanation: This error occurs because the
plotfunction in Matplotlib expects numerical data to plot. The error message points to a deeper issue in thelines.pyfile inside the Matplotlib library, but the actual problem originates from yourmy_datalist, which includes a string (โthreeโ) instead of a numeric value.Step 4: Trace the Error:
- The error originates in the
plt.plot(data)function call. - Matplotlibโs internal functions (
_xy_from_xyin this case) try to process the data but encounter an issue when they canโt convert the string โthreeโ into a float.
- The error originates in the
Step 5: Fix the Error: Correct the data by ensuring all elements are numeric.
my_data = [1, 2, 3, 4, 5] # Correcting the list to contain only integers generate_plot(my_data) # Now this will work without an error
Part 7: Tracing Errors in Jupyter Notebooks
When you run code in a Jupyter Notebook, the Python interpreter refers to the code in the notebook cells as it generates a stack trace when an error occurs. Hereโs how Jupyter Notebooks handle this:
How Jupyter Notebooks Generate Stack Traces
- Cell Execution:
- Each time you run a cell in a Jupyter Notebook, the code in that cell is executed by the Python interpreter. The code from each cell is treated as part of a sequential script, but each cell is an individual execution block.
- Input Label:
- Jupyter assigns each cell an input label, such as
In [1]:,In [2]:, etc. This label is used to identify the specific cell where the code was executed.
- Jupyter assigns each cell an input label, such as
- Stack Trace Generation:
- When an error occurs, Python generates a stack trace that shows the sequence of function calls leading to the error. In a Jupyter Notebook, this stack trace includes references to the notebook cells that were executed.
- The stack trace will point to the line number within the cell and the input label, such as
In [2], indicating where in your notebook the error originated.
- Example Stack Trace in Jupyter:
Suppose you have the following code in a cell labeled
In [2]:def divide(x, y): return x / y divide(10, 0)Running this code will generate a
ZeroDivisionError, and the stack trace might look like this:--------------------------------------------------------------------------- ZeroDivisionError Traceback (most recent call last) <ipython-input-2-d7d8f8a6c1c1> in <module> 2 return x / y 3 ----> 4 divide(10, 0) 5 <ipython-input-2-d7d8f8a6c1c1> in divide(x, y) 1 def divide(x, y): ----> 2 return x / y 3 4 divide(10, 0)Explanation:
- The
Traceback (most recent call last)shows the series of calls leading to the error. - The
<ipython-input-2-d7d8f8a6c1c1>refers to the code in cellIn [2]. - The stack trace pinpoints the exact line where the error occurred within that cell.
- The
- Multiple Cell References:
- If your code calls functions defined in different cells, the stack trace will show references to multiple cells. For example, if a function is defined in one cell and then called in another, the stack trace will include both cells in the sequence of calls.
- Limitations:
- The stack trace in Jupyter Notebooks is specific to the cells that have been executed. If you modify a cell and re-run it, the new code is associated with that cellโs input label, and previous stack traces will not reflect those changes.
Summary:
In Jupyter Notebooks, stack traces refer to the specific cells (In [X]) where the code was executed. The stack trace will show you the input label of the cell and the line number where the error occurred, helping you to quickly locate and fix issues in your notebook. Understanding how Jupyter references your code in stack traces is crucial for effective debugging.
General Summary of Stack Traces
What to Look For: In complex stack traces, start by looking at the error message itself, which often appears at the bottom of the stack. Work your way backward through the stack to identify where in your code the problem originated.
Tracing Function Calls: Understand how data flows through your functions. An error in a deeply nested function may often be triggered by an incorrect input or state set earlier in the code.
Error Summary
- Always read the error message carefully; it usually points directly to the problem.
SyntaxErrors - and, to a lesser extent,NameErrors are often due to small mistakes like typos, missing parentheses, or missing quotes.TypeErrors often occur when trying to perform operations on incompatible data types.AttributeErrors occur when you are trying to use a method that doesnโt exist for an object. These can also show up due to typos in your code that make the interpreter think you are trying to call a method.- While every error type has a specific meaning, always check your code for typos when trying to debug an error. Many typos do not prevent the interpreter from running your code and the eventual error caused by a typo might be hard to interpret!
By the end of this session, you should feel more comfortable identifying and fixing common Python errors. This skill is critical for debugging and developing more complex programs in the future.