8. Errors and Exceptions¶
Until now error messages haven’t been more than mentioned, but if you have tried out the examples you have probably seen some. There are (at least) two distinguishable kinds of errors: syntax errors and exceptions.
8.1. Syntax Errors¶
Syntax errors, also known as parsing errors, are perhaps the most common kind of complaint you get while you are still learning Python:
The parser repeats the offending line and displays a little ‘arrow’ pointing at the earliest point in the line where the error was detected. The error is caused by (or at least detected at) the token preceding the arrow: in the example, the error is detected at the function print() , since a colon ( ‘:’ ) is missing before it. File name and line number are printed so you know where to look in case the input came from a script.
8.2. Exceptions¶
Even if a statement or expression is syntactically correct, it may cause an error when an attempt is made to execute it. Errors detected during execution are called exceptions and are not unconditionally fatal: you will soon learn how to handle them in Python programs. Most exceptions are not handled by programs, however, and result in error messages as shown here:
The last line of the error message indicates what happened. Exceptions come in different types, and the type is printed as part of the message: the types in the example are ZeroDivisionError , NameError and TypeError . The string printed as the exception type is the name of the built-in exception that occurred. This is true for all built-in exceptions, but need not be true for user-defined exceptions (although it is a useful convention). Standard exception names are built-in identifiers (not reserved keywords).
The rest of the line provides detail based on the type of exception and what caused it.
The preceding part of the error message shows the context where the exception occurred, in the form of a stack traceback. In general it contains a stack traceback listing source lines; however, it will not display lines read from standard input.
Built-in Exceptions lists the built-in exceptions and their meanings.
8.3. Handling Exceptions¶
It is possible to write programs that handle selected exceptions. Look at the following example, which asks the user for input until a valid integer has been entered, but allows the user to interrupt the program (using Control — C or whatever the operating system supports); note that a user-generated interruption is signalled by raising the KeyboardInterrupt exception.
The try statement works as follows.
First, the try clause (the statement(s) between the try and except keywords) is executed.
If no exception occurs, the except clause is skipped and execution of the try statement is finished.
If an exception occurs during execution of the try clause, the rest of the clause is skipped. Then, if its type matches the exception named after the except keyword, the except clause is executed, and then execution continues after the try/except block.
If an exception occurs which does not match the exception named in the except clause, it is passed on to outer try statements; if no handler is found, it is an unhandled exception and execution stops with a message as shown above.
A try statement may have more than one except clause, to specify handlers for different exceptions. At most one handler will be executed. Handlers only handle exceptions that occur in the corresponding try clause, not in other handlers of the same try statement. An except clause may name multiple exceptions as a parenthesized tuple, for example:
A class in an except clause is compatible with an exception if it is the same class or a base class thereof (but not the other way around — an except clause listing a derived class is not compatible with a base class). For example, the following code will print B, C, D in that order:
Note that if the except clauses were reversed (with except B first), it would have printed B, B, B — the first matching except clause is triggered.
When an exception occurs, it may have associated values, also known as the exception’s arguments. The presence and types of the arguments depend on the exception type.
The except clause may specify a variable after the exception name. The variable is bound to the exception instance which typically has an args attribute that stores the arguments. For convenience, builtin exception types define __str__() to print all the arguments without explicitly accessing .args .
The exception’s __str__() output is printed as the last part (‘detail’) of the message for unhandled exceptions.
BaseException is the common base class of all exceptions. One of its subclasses, Exception , is the base class of all the non-fatal exceptions. Exceptions which are not subclasses of Exception are not typically handled, because they are used to indicate that the program should terminate. They include SystemExit which is raised by sys.exit() and KeyboardInterrupt which is raised when a user wishes to interrupt the program.
Exception can be used as a wildcard that catches (almost) everything. However, it is good practice to be as specific as possible with the types of exceptions that we intend to handle, and to allow any unexpected exceptions to propagate on.
The most common pattern for handling Exception is to print or log the exception and then re-raise it (allowing a caller to handle the exception as well):
The try … except statement has an optional else clause, which, when present, must follow all except clauses. It is useful for code that must be executed if the try clause does not raise an exception. For example:
The use of the else clause is better than adding additional code to the try clause because it avoids accidentally catching an exception that wasn’t raised by the code being protected by the try … except statement.
Exception handlers do not handle only exceptions that occur immediately in the try clause, but also those that occur inside functions that are called (even indirectly) in the try clause. For example:
8.4. Raising Exceptions¶
The raise statement allows the programmer to force a specified exception to occur. For example:
The sole argument to raise indicates the exception to be raised. This must be either an exception instance or an exception class (a class that derives from BaseException , such as Exception or one of its subclasses). If an exception class is passed, it will be implicitly instantiated by calling its constructor with no arguments:
If you need to determine whether an exception was raised but don’t intend to handle it, a simpler form of the raise statement allows you to re-raise the exception:
8.5. Exception Chaining¶
If an unhandled exception occurs inside an except section, it will have the exception being handled attached to it and included in the error message:
To indicate that an exception is a direct consequence of another, the raise statement allows an optional from clause:
This can be useful when you are transforming exceptions. For example:
It also allows disabling automatic exception chaining using the from None idiom:
For more information about chaining mechanics, see Built-in Exceptions .
8.6. User-defined Exceptions¶
Programs may name their own exceptions by creating a new exception class (see Classes for more about Python classes). Exceptions should typically be derived from the Exception class, either directly or indirectly.
Exception classes can be defined which do anything any other class can do, but are usually kept simple, often only offering a number of attributes that allow information about the error to be extracted by handlers for the exception.
Most exceptions are defined with names that end in “Error”, similar to the naming of the standard exceptions.
Many standard modules define their own exceptions to report errors that may occur in functions they define.
8.7. Defining Clean-up Actions¶
The try statement has another optional clause which is intended to define clean-up actions that must be executed under all circumstances. For example:
If a finally clause is present, the finally clause will execute as the last task before the try statement completes. The finally clause runs whether or not the try statement produces an exception. The following points discuss more complex cases when an exception occurs:
If an exception occurs during execution of the try clause, the exception may be handled by an except clause. If the exception is not handled by an except clause, the exception is re-raised after the finally clause has been executed.
An exception could occur during execution of an except or else clause. Again, the exception is re-raised after the finally clause has been executed.
If the finally clause executes a break , continue or return statement, exceptions are not re-raised.
If the try statement reaches a break , continue or return statement, the finally clause will execute just prior to the break , continue or return statement’s execution.
If a finally clause includes a return statement, the returned value will be the one from the finally clause’s return statement, not the value from the try clause’s return statement.
A more complicated example:
As you can see, the finally clause is executed in any event. The TypeError raised by dividing two strings is not handled by the except clause and therefore re-raised after the finally clause has been executed.
In real world applications, the finally clause is useful for releasing external resources (such as files or network connections), regardless of whether the use of the resource was successful.
8.8. Predefined Clean-up Actions¶
Some objects define standard clean-up actions to be undertaken when the object is no longer needed, regardless of whether or not the operation using the object succeeded or failed. Look at the following example, which tries to open a file and print its contents to the screen.
The problem with this code is that it leaves the file open for an indeterminate amount of time after this part of the code has finished executing. This is not an issue in simple scripts, but can be a problem for larger applications. The with statement allows objects like files to be used in a way that ensures they are always cleaned up promptly and correctly.
After the statement is executed, the file f is always closed, even if a problem was encountered while processing the lines. Objects which, like files, provide predefined clean-up actions will indicate this in their documentation.
8.9. Raising and Handling Multiple Unrelated Exceptions¶
There are situations where it is necessary to report several exceptions that have occurred. This is often the case in concurrency frameworks, when several tasks may have failed in parallel, but there are also other use cases where it is desirable to continue execution and collect multiple errors rather than raise the first exception.
The builtin ExceptionGroup wraps a list of exception instances so that they can be raised together. It is an exception itself, so it can be caught like any other exception.
By using except* instead of except , we can selectively handle only the exceptions in the group that match a certain type. In the following example, which shows a nested exception group, each except* clause extracts from the group exceptions of a certain type while letting all other exceptions propagate to other clauses and eventually to be reraised.
Note that the exceptions nested in an exception group must be instances, not types. This is because in practice the exceptions would typically be ones that have already been raised and caught by the program, along the following pattern:
8.10. Enriching Exceptions with Notes¶
When an exception is created in order to be raised, it is usually initialized with information that describes the error that has occurred. There are cases where it is useful to add information after the exception was caught. For this purpose, exceptions have a method add_note(note) that accepts a string and adds it to the exception’s notes list. The standard traceback rendering includes all notes, in the order they were added, after the exception.
For example, when collecting exceptions into an exception group, we may want to add context information for the individual errors. In the following each exception in the group has a note indicating when this error has occurred.
Python Debug Cheatsheet
A collection of my favorite Python debugging options
![]()
Logging
Basic
More Config
Multiple Log Files
Use different logger names for different log files.
ipdb (breakpoint)
ipdb is an enhanced version of pdb (built-in). It supports all pdb commands and is simply easier to use like tab for auto-complete.
Install: pip install ipdb
ipdb command cheatsheet. Check here for more commands.
Use ipdb.set_trace() to set a breakpoint.
Example:
ipdb (line by line)
You can run your code line by line without setting breakpoints in the file by:
It will start to execute from 1st line of the code a.py and you can use n or other ipdb commands to continue.
Exception
Understand Exception
Run and you will get an exception as follows.
The last line is the exception or root cause in other words.
Above that is so-called traceback. It traces the source of the exception. The error occurs in line #4 divide(1,0) , but the source is in line #2 inside function divide and you see that at the bottom of the traceback.
Print Exception
It is a good practice to specify the Error, i.e. ZeroDivisionError, if you want what to capture, otherwise you can use generic except Exception as ex .
Print Full Traceback
Interactive Mode
Run a script in interactive mode is a quick way (but limited) to debug crash, i.e. exception, without the need to add ipdb.set_trace() into the script.
Python does not quit after the exception so you check the variable values.
Run python -i a.py
Jupyter Notebook
Jupyter notebook is one of my favorite debugging tools. It is like a visual version of ipdb.
There is an implicit breakpoint after each cell (a block) of code. You can check/change variable values and continue with another block of code in the next cell.
Ctrl + Enter to run a cell.
VS Code Magic to Jupyter
Add #%% to an existing python file (.py) and you can run it as a Jupyter cell.
trace
The built-in trace module can print what lines are executed (similar to bash -x option) and the timing option is handy to debug performance issues on line level.
traceback — Print or retrieve a stack traceback¶
This module provides a standard interface to extract, format and print stack traces of Python programs. It exactly mimics the behavior of the Python interpreter when it prints a stack trace. This is useful when you want to print stack traces under program control, such as in a “wrapper” around the interpreter.
The module uses traceback objects — these are objects of type types.TracebackType , which are assigned to the __traceback__ field of BaseException instances.
Used to dump Python tracebacks explicitly, on a fault, after a timeout, or on a user signal.
Interactive source code debugger for Python programs.
The module defines the following functions:
traceback. print_tb ( tb , limit = None , file = None ) ¶
Print up to limit stack trace entries from traceback object tb (starting from the caller’s frame) if limit is positive. Otherwise, print the last abs(limit) entries. If limit is omitted or None , all entries are printed. If file is omitted or None , the output goes to sys.stderr ; otherwise it should be an open file or file-like object to receive the output.
Changed in version 3.5: Added negative limit support.
Print exception information and stack trace entries from traceback object tb to file. This differs from print_tb() in the following ways:
if tb is not None , it prints a header Traceback (most recent call last):
it prints the exception type and value after the stack trace
if type(value) is SyntaxError and value has the appropriate format, it prints the line where the syntax error occurred with a caret indicating the approximate position of the error.
Since Python 3.10, instead of passing value and tb, an exception object can be passed as the first argument. If value and tb are provided, the first argument is ignored in order to provide backwards compatibility.
The optional limit argument has the same meaning as for print_tb() . If chain is true (the default), then chained exceptions (the __cause__ or __context__ attributes of the exception) will be printed as well, like the interpreter itself does when printing an unhandled exception.
Changed in version 3.5: The etype argument is ignored and inferred from the type of value.
Changed in version 3.10: The etype parameter has been renamed to exc and is now positional-only.
This is a shorthand for print_exception(sys.exception(), limit, file, chain) .
traceback. print_last ( limit = None , file = None , chain = True ) ¶
This is a shorthand for print_exception(sys.last_type, sys.last_value, sys.last_traceback, limit, file, chain) . In general it will work only after an exception has reached an interactive prompt (see sys.last_type ).
traceback. print_stack ( f = None , limit = None , file = None ) ¶
Print up to limit stack trace entries (starting from the invocation point) if limit is positive. Otherwise, print the last abs(limit) entries. If limit is omitted or None , all entries are printed. The optional f argument can be used to specify an alternate stack frame to start. The optional file argument has the same meaning as for print_tb() .
Changed in version 3.5: Added negative limit support.
Return a StackSummary object representing a list of “pre-processed” stack trace entries extracted from the traceback object tb. It is useful for alternate formatting of stack traces. The optional limit argument has the same meaning as for print_tb() . A “pre-processed” stack trace entry is a FrameSummary object containing attributes filename , lineno , name , and line representing the information that is usually printed for a stack trace. The line is a string with leading and trailing whitespace stripped; if the source is not available it is None .
traceback. extract_stack ( f = None , limit = None ) ¶
Extract the raw traceback from the current stack frame. The return value has the same format as for extract_tb() . The optional f and limit arguments have the same meaning as for print_stack() .
traceback. format_list ( extracted_list ) ¶
Given a list of tuples or FrameSummary objects as returned by extract_tb() or extract_stack() , return a list of strings ready for printing. Each string in the resulting list corresponds to the item with the same index in the argument list. Each string ends in a newline; the strings may contain internal newlines as well, for those items whose source text line is not None .
traceback. format_exception_only ( exc , / [ , value ] ) ¶
Format the exception part of a traceback using an exception value such as given by sys.last_value . The return value is a list of strings, each ending in a newline. Normally, the list contains a single string; however, for SyntaxError exceptions, it contains several lines that (when printed) display detailed information about where the syntax error occurred. The message indicating which exception occurred is the always last string in the list.
Since Python 3.10, instead of passing value, an exception object can be passed as the first argument. If value is provided, the first argument is ignored in order to provide backwards compatibility.
Changed in version 3.10: The etype parameter has been renamed to exc and is now positional-only.
Format a stack trace and the exception information. The arguments have the same meaning as the corresponding arguments to print_exception() . The return value is a list of strings, each ending in a newline and some containing internal newlines. When these lines are concatenated and printed, exactly the same text is printed as does print_exception() .
Changed in version 3.5: The etype argument is ignored and inferred from the type of value.
Changed in version 3.10: This function’s behavior and signature were modified to match print_exception() .
This is like print_exc(limit) but returns a string instead of printing to a file.
traceback. format_tb ( tb , limit = None ) ¶
A shorthand for format_list(extract_tb(tb, limit)) .
traceback. format_stack ( f = None , limit = None ) ¶
A shorthand for format_list(extract_stack(f, limit)) .
traceback. clear_frames ( tb ) ¶
Clears the local variables of all the stack frames in a traceback tb by calling the clear() method of each frame object.
New in version 3.4.
Walk a stack following f.f_back from the given frame, yielding the frame and line number for each frame. If f is None , the current stack is used. This helper is used with StackSummary.extract() .
New in version 3.5.
Walk a traceback following tb_next yielding the frame and line number for each frame. This helper is used with StackSummary.extract() .
New in version 3.5.
The module also defines the following classes:
TracebackException Objects¶
New in version 3.5.
TracebackException objects are created from actual exceptions to capture data for later printing in a lightweight fashion.
class traceback. TracebackException ( exc_type , exc_value , exc_traceback , * , limit = None , lookup_lines = True , capture_locals = False , compact = False , max_group_width = 15 , max_group_depth = 10 ) ¶
Capture an exception for later rendering. limit, lookup_lines and capture_locals are as for the StackSummary class.
If compact is true, only data that is required by TracebackException ’s format method is saved in the class attributes. In particular, the __context__ field is calculated only if __cause__ is None and __suppress_context__ is false.
Note that when locals are captured, they are also shown in the traceback.
max_group_width and max_group_depth control the formatting of exception groups (see BaseExceptionGroup ). The depth refers to the nesting level of the group, and the width refers to the size of a single exception group’s exceptions array. The formatted output is truncated when either limit is exceeded.
A TracebackException of the original __cause__ .
A TracebackException of the original __context__ .
If self represents an ExceptionGroup , this field holds a list of TracebackException instances representing the nested exceptions. Otherwise it is None .
New in version 3.11.
The __suppress_context__ value from the original exception.
The __notes__ value from the original exception, or None if the exception does not have any notes. If it is not None is it formatted in the traceback after the exception string.
New in version 3.11.
A StackSummary representing the traceback.
The class of the original traceback.
For syntax errors — the file name where the error occurred.
For syntax errors — the line number where the error occurred.
For syntax errors — the end line number where the error occurred. Can be None if not present.
New in version 3.10.
For syntax errors — the text where the error occurred.
For syntax errors — the offset into the text where the error occurred.
For syntax errors — the end offset into the text where the error occurred. Can be None if not present.
New in version 3.10.
For syntax errors — the compiler error message.
classmethod from_exception ( exc , * , limit = None , lookup_lines = True , capture_locals = False ) ¶
Capture an exception for later rendering. limit, lookup_lines and capture_locals are as for the StackSummary class.
Note that when locals are captured, they are also shown in the traceback.
print ( * , file = None , chain = True ) ¶
Print to file (default sys.stderr ) the exception information returned by format() .
New in version 3.11.
Format the exception.
If chain is not True , __cause__ and __context__ will not be formatted.
The return value is a generator of strings, each ending in a newline and some containing internal newlines. print_exception() is a wrapper around this method which just prints the lines to a file.
The message indicating which exception occurred is always the last string in the output.
Format the exception part of the traceback.
The return value is a generator of strings, each ending in a newline.
Normally, the generator emits a single string; however, for SyntaxError exceptions, it emits several lines that (when printed) display detailed information about where the syntax error occurred.
The message indicating which exception occurred is always the last string in the output.
Changed in version 3.10: Added the compact parameter.
Changed in version 3.11: Added the max_group_width and max_group_depth parameters.
StackSummary Objects¶
New in version 3.5.
StackSummary objects represent a call stack ready for formatting.
class traceback. StackSummary ¶ classmethod extract ( frame_gen , * , limit = None , lookup_lines = True , capture_locals = False ) ¶
Construct a StackSummary object from a frame generator (such as is returned by walk_stack() or walk_tb() ).
If limit is supplied, only this many frames are taken from frame_gen. If lookup_lines is False , the returned FrameSummary objects will not have read their lines in yet, making the cost of creating the StackSummary cheaper (which may be valuable if it may not actually get formatted). If capture_locals is True the local variables in each FrameSummary are captured as object representations.
classmethod from_list ( a_list ) ¶
Construct a StackSummary object from a supplied list of FrameSummary objects or old-style list of tuples. Each tuple should be a 4-tuple with filename, lineno, name, line as the elements.
Returns a list of strings ready for printing. Each string in the resulting list corresponds to a single frame from the stack. Each string ends in a newline; the strings may contain internal newlines as well, for those items with source text lines.
For long sequences of the same frame and line, the first few repetitions are shown, followed by a summary line stating the exact number of further repetitions.
Changed in version 3.6: Long sequences of repeated frames are now abbreviated.
Returns a string for printing one of the frames involved in the stack. This method is called for each FrameSummary object to be printed by StackSummary.format() . If it returns None , the frame is omitted from the output.
New in version 3.11.
FrameSummary Objects¶
New in version 3.5.
A FrameSummary object represents a single frame in a traceback.
class traceback. FrameSummary ( filename , lineno , name , lookup_line = True , locals = None , line = None ) ¶
Represent a single frame in the traceback or stack that is being formatted or printed. It may optionally have a stringified version of the frames locals included in it. If lookup_line is False , the source code is not looked up until the FrameSummary has the line attribute accessed (which also happens when casting it to a tuple). line may be directly provided, and will prevent line lookups happening at all. locals is an optional local variable dictionary, and if supplied the variable representations are stored in the summary for later display.
Traceback Examples¶
This simple example implements a basic read-eval-print loop, similar to (but less useful than) the standard Python interactive interpreter loop. For a more complete implementation of the interpreter loop, refer to the code module.
The following example demonstrates the different ways to print and format the exception and traceback:
The output for the example would look similar to this:
The following example shows the different ways to print and format the stack:
Understanding Tracebacks in Python

Traceback is the message or information or a general report along with some data, provided by Python that helps us know about an error that has occurred in our program. It’s also called raising an exception in technical terms. For any development work, error handling is one of the crucial parts when a program is being written. So, the first step in handling errors is knowing the most frequent errors we will be facing in our code.
Tracebacks provide us with a good amount of information and some messages regarding the error that occurred while running the program. Thus, it’s very important to get a general understanding of the most common errors.
Tracebacks are often referred to with certain other names like stack trace, backtrace, or stack traceback. A stack is an abstract concept in all programming languages, which just refers to a place in the system’s memory or the processor’s core where the instructions are being executed one by one. And whenever there is an error while going through the code, tracebacks try to tell us the location as well as the kind of errors it has encountered while executing those instructions.
Some of the most common Tracebacks in Python
Here’s a list of the most common tracebacks that we encounter in Python. We will also try to understand the general meaning of these errors as we move further in this article.
- SyntaxError
- NameError
- IndexError
- TypeError
- AttributeError
- KeyError
- ValueError
- ModuleNotFound and ImportError
General overview of a Traceback in Python
Before going through the most common types of tracebacks, let’s try to get an overview of the structure of a general stack trace.
Python is trying to help us out by giving us all the information about an error that has occurred while executing the program. The last line of the output says that it’s supposedly a NameError and even suggesting us a solution. Python is also trying to tell us the line number that might be the source of the error.
We can see that we have a variable name mismatch in our code. Instead of using “result”, as we earlier declared in our code, we have written “results”, which throws an error while executing the program.
So, this is the general structural hierarchy for a Traceback in Python which also implies that Python tracebacks should be read from bottom to top, which is not the case in most other programming languages.
Understanding Tracebacks
1. SyntaxError
All programming languages have their specific syntax. If we miss out on that syntax, the program will throw an error. The code has to be parsed first only then it will give us the desired output. Thus, we have to make sure of the correct syntax for it to run correctly.
Let’s try to see the SyntaxError exception raised by Python.
When we try to run the above code, we see a SyntaxError exception being raised by Python. To print output in Python3.x, we need to wrap it around with a parenthesis. We can see the location of our error too, with the “^” symbol displayed below our error.
2. NameError
While writing any program, we declare variables, functions, and classes and also import modules into it. While making use of these in our program, we need to make sure that the declared things should be referenced correctly. On the contrary, if we make some kind of mistake, Python will throw an error and raise an exception.
Let’s see an example of NameError in Python.
Our traceback says that the name “multipli” is not defined and it’s a NameError. We have not defined the variable “multipli”, hence the error occurred.
3. IndexError
Working with indexes is a very common pattern in Python. We have to iterate over various data structures in Python to perform operations on them. Index signifies the sequence of a data structure such as a list or a tuple. Whenever we try to retrieve some kind of index data from a series or sequence which is not present in our data structure, Python throws an error saying that there is an IndexError in our code.
Let’s see an example of it.
Our traceback says that we have an IndexError at line 5. It’s evident from our stack trace that our list does not contain any element at index 5, and thus it is out of range.
4. TypeError
Python throws a TypeError when trying to perform an operation or use a function with the wrong type of objects being used together in that operation.
Let’s see an example.
Output:
In our code, we are trying to calculate the sum of two numbers. But Python is raising an exception saying that there is a TypeError for the operand “+” at line number 6. The stack trace is telling us that the addition of an integer and a string is invalid since their types do not match.
5. AttributeError
Whenever we try to access an attribute on an object which is not available on that particular object, Python throws an Attribute Error.
Let’s go through an example.
Python says that there is an AttributeError for the object “tuple” at line 5. Since tuples are immutable data structures and we are trying to use the method “append” on it. Thus, there is an exception raised by Python here. Tuple objects do not have an attribute “append” as we are trying to mutate the same which is not allowed in Python.
6. KeyError
Dictionary is another data structure in Python. We use it all the time in our programs. It is composed of Key: Value pairs and we need to access those keys and values whenever required. But what happens if we try to search for a key in our dictionary which is not present?
Let’s try using a key that is not present and see what Python has to say about that.
In the above example, we are trying to access the value for the key “email”. Well, Python searched for the key “email” in our dictionary object and raised an exception with a stack trace. The traceback says, there is a KeyError in our program at line 5. The provided key is nowhere to be found in the specified object, hence the error.
7. ValueError
The ValueError exception is raised by Python, whenever there is an incorrect value in a specified data type. The data type of the provided argument may be correct, but if it’s not an appropriate value, Python will throw an error for it.
Let’s see an example.
In the example above, we are trying to get the square root of a number using the in-built math module in Python. We are using the correct data type “int” as an argument to our function, but Python is throwing a traceback with ValueError as an exception.
This is because we can’t get a square root for a negative number, hence, it’s an incorrect value for our argument and Python tells us about the error saying that it’s a ValueError at line 10.
8. ImportError and ModuleNotFoundError
ImportError exception is raised by Python when there is an error in importing a specific module that does not exist. ModuleNotFound comes up as an exception when there is an issue with the specified path for the module which is either invalid or incorrect.