0% found this document useful (0 votes)
24 views23 pages

Unit 3 Python

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
0% found this document useful (0 votes)
24 views23 pages

Unit 3 Python

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
Download as pdf or txt
You are on page 1/ 23

UNIT-III : Exception Handling and Multi-Threading in python

Unit 3
Exception Handling and Multi-Threading in python
Exception handling: try, except and finally block, handling multiple exceptions, raise an
exception, User defined exception- python multithreading- thread and threading module-
Synchronizing Threads in Python.
Case Study: Development of student performance evaluation report

Exception Handling
An exception is a Python object that represents an error. When a Python script raises an exception, it
must either handle the exception immediately otherwise it terminates and quits.
The try block lets you test a block of code for errors.
The except block lets you handle the error.
The else block lets you execute code when there is no error.
The finally block lets you execute code, regardless of the result of the try- and except blocks.
Exception Handling
When an error occurs, or exception as we call it, Python will normally stop and generate an error
message.
These exceptions can be handled using the try statement:
The try block will generate an exception, because x is not defined:
try:
print(x)
except:
print("An exception occurred")
Since the try block raises an error, the except block will be executed.
Without the try block, the program will crash and raise an error:
This statement will raise an error, because x is not defined:
print(x)
List of Standard Exceptions −
Sr.No. Exception Name & Description
1 Exception
Base class for all exceptions
2 StopIteration
Raised when the next() method of an iterator does not point to any object.
3 SystemExit
Raised by the sys.exit() function.
4 StandardError
Base class for all built-in exceptions except StopIteration and SystemExit.
5 ArithmeticError
Base class for all errors that occur for numeric calculation.
6 OverflowError
Raised when a calculation exceeds maximum limit for a numeric type.
7 FloatingPointError
Raised when a floating point calculation fails.
8 ZeroDivisionError
Raised when division or modulo by zero takes place for all numeric types.
9 AssertionError
Raised in case of failure of the Assert statement.
10 AttributeError
Raised in case of failure of attribute reference or assignment.
11 EOFError
Raised when there is no input from either the raw_input() or input() function and the end of file is
reached.
12 ImportError
Raised when an import statement fails.
13 KeyboardInterrupt
Raised when the user interrupts program execution, usually by pressing Ctrl+c.
14 LookupError
Base class for all lookup errors.
15 IndexError
Raised hen an index is not found in a sequence.
16 KeyError
Raised when the specified key is not found in the dictionary.
17 NameError
Raised when an identifier is not found in the local or global namespace.
18 UnboundLocalError
Raised when trying to access a local variable in a function or method but no value has been assigned
to it.
19 EnvironmentError
Base class for all exceptions that occur outside the Python environment.
20 IOError
Raised when an input/ output operation fails, such as the print statement or the open() function when
trying to open a file that does not exist.
21 IOError
Raised for operating system-related errors.
22 SyntaxError
Raised when there is an error in Python syntax.
23 IndentationError
Raised when indentation is not specified properly.
24 SystemError
Raised when the interpreter finds an internal problem, but when this error is encountered the Python
interpreter does not exit.
25 SystemExit
Raised when Python interpreter is quit by using the sys.exit() function. If not handled in the code,
causes the interpreter to exit.
26 TypeError
Raised when an operation or function is attempted that is invalid for the specified data type.
27 ValueError
Raised when the built-in function for a data type has the valid type of arguments, but the arguments
have invalid values specified.
28 RuntimeError
Raised when a generated error does not fall into any category.
29 NotImplementedError
Raised when an abstract method that needs to be implemented in an inherited class is not actually
implemented.
Many Exceptions
You can define as many exception blocks as you want, e.g. if you want to execute a special block of
code for a special kind of error:
Print one message if the try block raises a NameError and another for other errors:
try:
print(x)
except NameError:
print("Variable x is not defined")
except:
print("Something else went wrong")
Else
You can use the else keyword to define a block of code to be executed if no errors were raised:
try:
print("Hello")
except:
print("Something went wrong")
else:
print("Nothing went wrong")
Finally
The finally block, if specified, will be executed regardless if the try block raises an error or not.
try:
print(x)
except:
print("Something went wrong")
finally:
print("The 'try except' is finished")
Try to open and write to a file that is not writable:
try:
f = open("demofile.txt")
try:
f.write("Lorum Ipsum")
except:
print("Something went wrong when writing to the file")
finally:
f.close()
except:
print("Something went wrong when opening the file")
The program can continue, without leaving the file object open.

Exception handling in Python is a way to handle runtime errors that occur during the execution of a
program. These errors can be caused by various factors such as invalid input, network failures, file
errors, or programming mistakes. By handling these exceptions, you can prevent your program from
crashing and provide a more informative message to the user.
In Python, you can handle exceptions using a try-except block. Here's an example:
try:
# Code that might raise an exception
x = int(input("Enter a number: "))
y = int(input("Enter another number: "))
result = x / y
print("The result is", result)
except ValueError:
# Exception handling code for invalid input
print("Invalid input. Please enter a number.")
except ZeroDivisionError:
# Exception handling code for division by zero
print("Division by zero is not allowed.")
except:
# Exception handling code for any other exception
print("An error occurred.")

Raising an exception:
Raise an exception
As a Python developer you can choose to throw an exception if a condition occurs.
To throw (or raise) an exception, use the raise keyword.
ExampleGet your own Python Server
Raise an error and stop the program if x is lower than 0:
x = -1
if x < 0:
raise Exception("Sorry, no numbers below zero")
The raise keyword is used to raise an exception.
You can define what kind of error to raise, and the text to print to the user.
ExampleGet your own Python Server
Raise a TypeError if x is not an integer:
x = "hello"
if not type(x) is int:
raise TypeError("Only integers are allowed")

You can raise an exception in Python using the raise keyword followed by an exception type. Here's
an example:
x = -1
if x < 0:
raise ValueError("Invalid input. The value must be non-negative.")
In this program, we check if the value of x is negative. If it is, we raise a ValueError exception with a
custom error message. This will terminate the program and display the error message to the user.
User-defined exception:
You can define your own custom exceptions in Python by creating a new class that inherits from the
built-in Exception class. Here's an example:
class MyException(Exception):
pass

x = 10

if x > 5:
raise MyException("The value of x is too high.")
In this program, we define a new exception class called MyException. We then check if the value of x
is greater than 5. If it is, we raise a MyException exception with a custom error message. This will
terminate the program and display the error message to the user.
Multithreading in Python:
Multithreading is a technique that allows a program to perform multiple tasks concurrently. In Python,
you can create threads using the built-in threading module. Here's an example:
python
Copy code
import threading
def task():
print("Executing task...")
# Do some work here...

t1 = threading.Thread(target=task)
t2 = threading.Thread(target=task)

t1.start()
t2.start()

t1.join()
t2.join()

print("All tasks completed.")


In this program, we define a function called task that performs some work. We then create two threads
using the Thread class from the threading module and assign the task function as the target. We start
both threads using the start method and then wait for them to complete using the join method. Finally,
we print a message indicating that all tasks have been completed.

Synchronizing threads in Python:


When using multiple threads in a program, you may need to synchronize them to prevent race
conditions or other concurrency issues. In Python,

Python Exceptions

When a Python program meets an error, it stops the execution of the rest of the program. An
error in Python might be either an error in the syntax of an expression or a Python exception

What is an Exception?

An exception in Python is an incident that happens while executing a program that causes the
regular course of the program's commands to be disrupted. When a Python code comes across
a condition it can't handle, it raises an exception. An object in Python that describes an error
is called an exception.

When a Python code throws an exception, it has two options: handle the exception
immediately or stop and quit.
Exceptions versus Syntax Errors

When the interpreter identifies a statement that has an error, syntax errors occur. Consider the
following scenario:

Code

1. #Python code after removing the syntax error


2. string = "Python Exceptions"
3.
4. for s in string:
5. if (s != o:
6. print( s )

Output:

if (s != o:
^
SyntaxError: invalid syntax

The arrow in the output shows where the interpreter encountered a syntactic error. There was
one unclosed bracket in this case. Close it and rerun the program:

Code

1. #Python code after removing the syntax error


2. string = "Python Exceptions"
3.
4. for s in string:
5. if (s != o):
6. print( s )

Output:

2 string = "Python Exceptions"


4 for s in string:
----> 5 if (s != o):
6 print( s )

NameError: name 'o' is not defined

We encountered an exception error after executing this code. When syntactically valid Python
code produces an error, this is the kind of error that arises. The output's last line specified the
name of the exception error code encountered. Instead of displaying just "exception error",
Python displays information about the sort of exception error that occurred. It was a
NameError in this situation..

Try and Except Statement - Catching Exceptions

In Python, we catch exceptions and handle them using try and except code blocks. The try
clause contains the code that can raise an exception, while the except clause contains the code
lines that handle the exception. Let's see if we can access the index from the array, which is
more than the array's length, and handle the resulting exception.

Code

1. # Python code to catch an exception and handle it using try and except code blocks
2.
3. a = ["Python", "Exceptions", "try and except"]
4. try:
5. #looping through the elements of the array a, choosing a range that goes beyond th
e length of the array
6. for i in range( 4 ):
7. print( "The index and element from the array is", i, a[i] )
8. #if an error occurs in the try block, then except block will be executed by the Python
interpreter
9. except:
10. print ("Index out of range")

Output:

The index and element from the array is 0 Python


The index and element from the array is 1 Exceptions
The index and element from the array is 2 try and except
Index out of range

The code blocks that potentially produce an error are inserted inside the try clause in the
preceding example. The value of i greater than 2 attempts to access the list's item beyond its
length, which is not present, resulting in an exception. The except clause then catches this
exception and executes code without stopping it.

How to Raise an Exception

If a condition does not meet our criteria but is correct according to the Python interpreter, we
can intentionally raise an exception using the raise keyword. We can use a customized
exception in conjunction with the statement.

If we wish to use raise to generate an exception when a given condition happens,


Code

1. #Python code to show how to raise an exception in Python


2. num = [3, 4, 5, 7]
3. if len(num) > 3:
4. raise Exception( f"Length of the given list must be less than or equal to 3 but is {l
en(num)}" )

Output:

1 num = [3, 4, 5, 7]
2 if len(num) > 3:
----> 3 raise Exception( f"Length of the given list must be less than or equal to 3 but is
{len(num)}" )

Exception: Length of the given list must be less than or equal to 3 but is 4

The implementation stops and shows our exception in the output, providing indications as to
what went incorrect.

Assertions in Python

When we're finished verifying the program, an assertion is a consistency test that we can
switch on or off.

The simplest way to understand an assertion is to compare it with an if-then condition. An


exception is thrown if the outcome is false when an expression is evaluated.

Assertions are made via the assert statement, which was added in Python 1.5 as the latest
keyword.

Assertions are commonly used at the beginning of a function to inspect for valid input and at
the end of calling the function to inspect for valid output.

The assert Statement

Python examines the adjacent expression, preferably true when it finds an assert statement.
Python throws an AssertionError exception if the result of the expression is false.

The syntax for the assert clause is −

1. assert Expressions[, Argument]

Python uses ArgumentException, if the assertion fails, as the argument for the AssertionError.
We can use the try-except clause to catch and handle AssertionError exceptions, but if they
aren't, the program will stop, and the Python interpreter will generate a traceback.
Code

1. #Python program to show how to use assert keyword


2. # defining a function
3. def square_root( Number ):
4. assert ( Number >0), "Give a positive integer"
5. return Number**(1/2)
6.
7. #Calling function and passing the values
8. print( square_root( 36 ) )
9. print( square_root( -36 ) )

Output:

7 #Calling function and passing the values


----> 8 print( square_root( 36 ) )
9 print( square_root( -36 ) )

Input In [23], in square_root(Number)


3 def square_root( Number ):
----> 4 assert ( Number < 0), "Give a positive integer"
5 return Number**(1/2)

AssertionError: Give a positive integer

Try with Else Clause

Python also supports the else clause, which should come after every except clause, in the try,
and except blocks. Only when the try clause fails to throw an exception the Python interpreter
goes on to the else block.

Here is an instance of a try clause with an else clause.

Code

1. # Python program to show how to use else clause with try and except clauses
2.
3. # Defining a function which returns reciprocal of a number
4. def reciprocal( num1 ):
5. try:
6. reci = 1 / num1
7. except ZeroDivisionError:
8. print( "We cannot divide by zero" )
9. else:
10. print ( reci )
11. # Calling the function and passing values
12. reciprocal( 4 )
13. reciprocal( 0 )

Output:

0.25
We cannot divide by zero

Finally Keyword in Python

The finally keyword is available in Python, and it is always used after the try-except block.
The finally code block is always executed after the try block has terminated normally or after
the try block has terminated for some other reason.

Here is an example of finally keyword with try-except clauses:

Code

1. # Python code to show the use of finally clause


2.
3. # Raising an exception in try block
4. try:
5. div = 4 // 0
6. print( div )
7. # this block will handle the exception raised
8. except ZeroDivisionError:
9. print( "Atepting to divide by zero" )
10. # this will always be executed no matter exception is raised or not
11. finally:
12. print( 'This is code of finally clause' )

Output:

Atepting to divide by zero


This is code of finally clause

Python Built-in Exceptions

Illegal operations can raise exceptions. There are plenty of built-in exceptions in Python that
are raised when corresponding errors occur.
We can view all the built-in exceptions using the built-in local() function as follows:
print(dir(locals()['__builtins__']))
Run Code

Here, locals()['__builtins__'] will return a module of built-in exceptions, functions, and


attributes and dir allows us to list these attributes as strings.
Some of the common built-in exceptions in Python programming along with the error that
cause them are listed below:

Exception Cause of Error

AssertionError Raised when an assert statement fails.

Raised when attribute assignment or reference fails.


AttributeError
(eg:trying to use append function in normal integer variable)

Raised when the input() function hits end-of-file


condition.(eg:a=input())
EOFError
Print(a))when we doesn’t assign value to the variable and
trying to print that

FloatingPointError Raised when a floating point operation fails.

GeneratorExit Raise when a generator's close() method is called.

ImportError Raised when the imported module is not found.

IndexError Raised when the index of a sequence is out of range.

KeyError Raised when a key is not found in a dictionary.

Raised when the user hits the interrupt key (Ctrl+C or


KeyboardInterrupt
Delete).

MemoryError Raised when an operation runs out of memory.

NameError Raised when a variable is not found in local or global scope.

NotImplementedError Raised by abstract methods.

OSError Raised when system operation causes system related error.


Raised when the result of an arithmetic operation is too large
OverflowError
to be represented.

Raised when a weak reference proxy is used to access a


ReferenceError
garbage collected referent.

RuntimeError Raised when an error does not fall under any other category.

Raised by next() function to indicate that there is no further


StopIteration
item to be returned by iterator.

SyntaxError Raised by parser when syntax error is encountered.

IndentationError Raised when there is incorrect indentation.

Raised when indentation consists of inconsistent tabs and


TabError
spaces.

Raised when interpreter detects internal error.(cannot be


SystemError recogonized by os,violation against rules to define some
functions)

SystemExit Raised by sys.exit() function.(trying to exit the system )

Raised when a function or operation is applied to an object


TypeError
of incorrect type.

Raised when a reference is made to a local variable in a


UnboundLocalError function or method, but no value has been bound to that
variable.

Raised when a Unicode-related encoding or decoding error


UnicodeError
occurs.

Raised when a Unicode-related error occurs during


UnicodeEncodeError
encoding.

Raised when a Unicode-related error occurs during


UnicodeDecodeError
decoding.

Raised when a Unicode-related error occurs during


UnicodeTranslateError
translating.
Raised when a function gets an argument of correct type but
ValueError
improper value.

Raised when the second operand of division or modulo


ZeroDivisionError
operation is zero.

Defining Custom Exceptions

In Python, we can define custom exceptions by creating a new class that is derived from the
built-in Exception class.
Here's the syntax to define custom exceptions,

class CustomError(Exception):
...
pass

try:
...

except CustomError:
...

Here, CustomError is a user-defined error which inherits from the Exception class.

Example: Python User-Defined Exception


# define Python user-defined exceptions
class InvalidAgeException(Exception):
"Raised when the input value is less than 18"
pass

# you need to guess this number


number = 18

try:
input_num = int(input("Enter a number: "))
if input_num < number:
raise InvalidAgeException
else:
print("Eligible to Vote")

except InvalidAgeException:
print("Exception occurred: Invalid Age")
Run Code
Output
If the user input input_num is greater than 18,

Enter a number: 45
Eligible to Vote

If the user input input_num is smaller than 18,

Enter a number: 14
Exception occurred: Invalid Age

In the above example, we have defined the custom exception InvalidAgeException by


creating a new class that is derived from the built-in Exception class.
Here, when input_num is smaller than 18, this code generates an exception
How to Catch Multiple

To catch multiple Exceptions in Python:

When a program encounters an exception during execution, it is terminated if the exception is


not handled. By handling multiple exceptions, a program can respond to different exceptions
without terminating it.

In Python, try-except blocks can be used to catch and respond to one or multiple exceptions.
In cases where a process raises more than one possible exception, they can all be handled
using a single except clause.

Using Same Code Block for Multiple Exceptions

With this approach, the same code block is executed if any of the listed exceptions occurs.
Here's an example:

try:
name = 'Bob'
name += 5
except (NameError, TypeError) as error:
print(error)

In the above example, the code in the except block will be executed if any of the listed
exceptions occurs. Running the above code raises a TypeError, which is handled by the code,
producing the following output:

cannot concatenate 'str' and 'int' objects


Using Different Code Blocks for Multiple Exceptions

If some exceptions need to be handled differently, they can be placed in their


own except clause:

try:
name = 'Bob'
name += 5
except NameError as ne:
# Code to handle NameError
print(ne)

except TypeError as te:


# Code to handle TypeError
print(te)

In the above example, NameError and TypeError are two possible exceptions in the code,
which are handled differently in their own except blocks.

Multithreading in Python

What is a Process?

A program in execution is known as a process. When you start any app or program on your
computer, such as the internet browser, the operating system treats it as a process.

A process may consist of several threads of execution that may execute concurrently. In other
words, we can say a process facilitates multithreading.

What is a Thread?

a thread is synonymous with lightweight processes. So a thread is nothing but an independent


flow of execution. It can also be defined as an instance of a process.Simply put, a thread is a
sequence of instructions that the computer performs. It is executed independently. Depending
on the scenario, a thread can also be pre-empted or put to sleep.

Note-Preemption refers to the action of stopping a task temporarily to continue it at a later


time. So, in this case, the thread can be temporarily interrupted by the processor.

To facilitate multithreading in Python, we can make use of the following modules offered by
Python –

 Thread Module
 Threading Module

What is Multithreading in Python?


Multithreading in Python is a popular technique that enables multiple tasks to be executed
simultaneously. In simple words, the ability of a processor to execute multiple threads
simultaneously is known as multithreading.

Python multithreading facilitates sharing data space and resources of multiple threads with the
main thread. It allows efficient and easy communication between the threads.

What is Multiprocessing?

The ability of a processor to execute several unrelated processes simultaneously is known as


multiprocessing. These processes do not share any resources.

Multiprocessing breaks down processes into smaller routines that run independently. The
more tasks a single processor is burdened with, the more difficult it becomes for the processor
to keep track of them.

It evidently gives rise to the need for multiprocessing. Multiprocessing tries to ensure that
every processor gets its own processor/processor core and that execution is hassle-free.

Note-In the case of multicore processor systems like Intel i3, a processor core is allotted to a
process.

Python Multithreading vs Multiprocessing

The main differences to note between Multithreading and Multiprocessing are as follows –

Multithreading Multiprocessing
It is a technique where a process spawns It is the technique where multiple processes run across
multiple threads simultaneously. multiple processors/processor cores simultaneously.
Python multithreading implements Python multiprocessing implements parallelism in its
concurrency. truest form.
It gives the illusion that they are running It is parallel in the sense that the multiprocessing module
parallelly, but they work in a concurrent facilitates the running of independent processes
manner. parallelly by using subprocesses.
In multithreading, the GIL or Global
In multiprocessing, each process has its own Python
Interpreter Lock prevents the threads from
Interpreter performing the execution.
running simultaneously.

Why and When to Use Multithreading in Python?

If you wish to break down your tasks and applications into multiple sub-tasks and then execute
them simultaneously, then multithreading in Python is your best bet.

All important aspects such as performance, rendering, speed and time consumption will
drastically be improved by using proper Python multithreading.

Multithreading in Python should be used only when there is no existing inter-dependency


between the threads.
Starting a New Thread

.Python offers a standard library called "threading" to perform multithreading in Python.

The syntax to create a new thread is as follows –

In Python multithreading, there are two ways in which you can start a new thread-

1. Using the Threading Module

Let's take a look at the code using which we can create a new thread using the Threading
Module –

from threading import *


def MyThread1():
print("I am in thread1.", "Current Thread in Execution is", current_thread().getName())
def MyThread2():
print("I am in thread2.", "Current Thread in Execution is", current_thread().getName())
t1 = Thread(target=MyThread1, args=[])
t2 = Thread(target=MyThread2, args=[])
t1.start()
t2.start()

Output:

I am in thread1. Current Thread in Execution is Thread-1


I am in thread2. Current Thread in Execution is Thread-2

2. Using the Thread Module

The way to create a new thread using the Thread module is as follows –

import _thread
def MyThread1():
print("This is thread1")
def MyThread2():
print("This is thread2")

_thread.start_new_thread(MyThread1, ())
_thread.start_new_thread(MyThread2, ())

Output:

This is thread1
This is thread2

Note: The output of the above code snippet can differ for different runs. It happens because
multithreading in Python using the _thread module is unstable.
No one can tell which thread is going to get executed first. The _thread module treats threads
as functions while the Threading module is implemented in an object-oriented way, which
means every thread corresponds to an object.

The Threading module is preferred as its intuitive APIs help us synchronize thread executions,
thus making it predictable and highly reliable.

Using the ThreadPoolExecutor

The easiest way to work with multiple threads is by using the ThreadPoolExecutor, part of the
standard Python library. It falls under the concurrent.features library.

Using the with statement, you can create a context manager. It would enable you to create and
delete a pool efficiently. We can also import the ThreadPoolExecutor directly from the
concurrent.features library.

The syntax for creating a ThreadPoolExecutor is-

executor = ThreadPoolExecutor(max_workers=””)

The max_worker parameter can take any integer value based on the scenario.

Let's take a look at the following code to see how to achieve this –

from concurrent.futures import ThreadPoolExecutor


import threading
import random

def task():
print("Executing the given task")
result = 0
i=0
for i in range(10):
result = result + i
print("I: {}".format(result))
print("The task is executed {}".format(threading.current_thread()))

def main():
executor = ThreadPoolExecutor(max_workers=3)
task1 = executor.submit(task)
task2 = executor.submit(task)

if __name__ == '__main__':
main()

Output –

Executing the given task


I: 45
Executing the given task
The task is ececuted <Thread (ThreadPoolExecutor-0_0, started demon 140411580180224)
>
I: 45
The task is ececuted <Thread (ThreadPoolExecutor-0_0, started demon 140411571787520)
>

The Threading Module

The threading module is the high-level implementation of multithreading in Python. It is the


go-to approach for managing multithreaded applications. The benefits of the Threading
module outweigh the ones of the Thread module.

Along with the methods of the Thread module, the Threading module offers additional
methods such as –

 threading.activeCount() − This returns the number of active thread objects.


 threading.currentThread() − This returns the number of objects that are under the
thread control of the caller.
 threading.enumerate() −This returns the list of all thread objects that are presently
active

Race Conditions

Race conditions are one of the primary issues you will face while working with multithreading
in Python.

Most commonly, race conditions happen when two or more threads access the shared piece of
data and resource. In real-time multithreading in Python, it can occur when threads overlap.
The solution to this is synchronizing threads which we will see further.

Synchronizing Threads

In Python, you can implement the locking mechanism to enable you to synchronize the
threads.

The low-level synchronization primitive lock is implemented through the _thread module.

A thread can have one of the following two states –

 Locked
 Unlocked

The class that is used to implement primitive locks is known as Lock. Lock objects are created
to make the threads run synchronously. Only one thread at a time can have a lock.

The two methods supported by a lock object are –

1. acquire()– This method changes the state of an unlocked lock. But if it is already
locked, the acquire() method is blocked.
2. release()– This method is used to free up the locks when no longer required. It can be
called by any state, irrespective of their state.

The parameter that we pass through the Lock class' acquire() method is known as the blocking
parameter.

Let's assume we have a thread object T to understand how all these work together. As
mentioned before, if we wish to call the acquire() method for T, we will pass the blocking
parameter through it.

The blocking parameter can have only two possible values- True or False. It gives rise to two
scenarios.

 Scenario 1: When the blocking parameter is set to True, and we call the acquire
method as T.acquire(blocking=True), the thread object will acquire the lock T. This
can happen only when T has no existing locks. On the flip side, if the thread object T
is already locked, the acquire() call is suspended, and it waits until T releases the lock.
The moment thread T frees up, the calling thread immediately re-locks it. The calling
thread then acquires the released lock.
 Scenario 2: When the blocking parameter is set to False, and T is unlocked, it acquires
a lock and returns True. Whereas if T is already locked and the blocking parameter is
set to False, the acquire method does not affect T. It simply returns False.

Multithreading Priority Queues

A new queue object can be created using the Queue module. It can hold a specific number of
items.

You can use the following methods to control the queue –

 get()– It returns and removes an item from the queue.


 put()– It adds an item to the queue.
 qsize()– It returns the number of items currently in the queue.
 empty()– It returns True or False based on whether the queue is empty or not.
 full()– It returns True if the queue is full otherwise, it returns False.

Check out this article to learn more about Queue in Python.

Threading Objects

1. Semaphore
2. Timer
3. Barrier

1. Semaphore

 The threading. Semaphore is the first on the list.


 It is a counter with certain special properties.
 Since the counting is atomic, you can be sure that the operating system will not switch
the thread in the middle of an increment or decrement.
 The counter is incremented when threading.release() is called.
 The counter is decremented when threading.acquire() is called.

2. Time

 The object used to schedule a function to be called after a certain amount of time has
passed is the threading.Timer.
 The Timer is started by using the .start() method.
 The Timer is stopped by using the .cancel() method.

3. Barrier

 The object used to keep multiple threads in sync is the threading.Barrier() object.
 You need to specify the number of threads to be synchronized while creating the
Barrier.
 The .wait() method is called by each thread on a Barrier.

Advantages of Multithreading in Python

Multithreading in Python has several advantages, making it a popular approach. Let's take
a look at some of them –

 Python multithreading enables efficient utilization of the resources as the threads share
the data space and memory.
 Multithreading in Python allows the concurrent and parallel occurrence of various
tasks.
 It causes a reduction in time consumption or response time, thereby increasing the
performance.

You might also like