PP_Module-3 Notes
PP_Module-3 Notes
Features of RegEx:
Hundreds of code could be reduced to a one line elegant regularexpression
Used to construct compilers, interpreters and texteditors
Used to search and match textpatterns
Used to validate text data formats especially inputdata
Popular programming languages have Regex capabilities Python, Perl, JavaScript,Ruby
,C++,C#
Here,[abc]willmatchifthestringyouaretryingtomatchcontainsanyofthea,borc.
You canalsospecifyarangeofcharactersusing-inside squarebrackets. [a-e]
is the same as[abcde].
[1-4] is the same as [1234].
[0-9] is the same as [0123456789].
You can complement (invert) the character set by using caret ^ symbol at the start of a
square-bracket.:
[^abc] means any character except a or b or c.
[^0-9] means any non-digit character.
Output:
Printing all the characters from a to m in the given string:
['h', 'i', 'i', 'h', 'g', 'a', 'm', 'm', 'i', 'g', 'd', 'l', 'e']
Printing all the characters of the string except i:
['T', 'h', 's', ' ', 's', ' ', 'P', 'y', 't', 'h', 'o', 'n', ' ', 'p', 'r', 'o', 'g', 'r', 'a', 'm', 'm', 'n', 'g', ' ', 'M', 'o', 'd', 'u', 'l',
'e', '-', '3']
Printing numbers from the given string:
['3']
Whether letter, number, whitespace not including "\n," printable, nonprintable, or a
symbol, the dot can match themall.
Example to demonstrate a dot or period symbol::
import re
pattern1 = ".o"
pattern2="p .... n"
pattern3="p ........ n"
string="This is Python programming Module-3“
result=re.findall(pattern1,string)
print("Printing a word ends with 'o':")
print(result)
result=re.findall(pattern2,string,re.I)
print("Printing a word starts with 'p/P' and ends with 'o':")
print(result)
result=re.findall(pattern3,string)
print("Printing a word starts with 'p' and ends with 'o':")
print(result)
Output:
Printing a word ends with 'o':
['ho', 'ro', 'Mo']
Printing a word starts with 'p/P' and ends with 'o':
['Python']
Printing a word starts with 'p' and ends with 'o':
['programmin']
Output:
Printing a first character of string:
['T']
Printing the first two words of string:
['This is']
Printing an empty list:
[]
4. Dollar ($)Symbol:
The dollar symbol $ is used to check if a string ends with a certaincharacter.
Output:
Printing last character of string:
['3']
Printing last word of string:
['Module-3']
Printing an empty list:
[]
5. Star (*)Symbol:
The star symbol * matches zero or more occurrences of the pattern left toit.
6. Plus(+)symbol:
The plus symbol + matches one or more occurrences of the pattern left toit.
Output:
Printing an empty list:
[]
Printing all alphabets of a string:
['This', 'is', 'Python', 'programming', 'Module']
Printing all characters except alphabets:
[' ', ' ', ' ', ' ', '-3']
Output:
Printing an empty list:
[]
Printing a word of a string:
['Python']
Printing a word of a string:
['Python']
8. Braces{}:
Consider this code: {n,m}. This means at least n, and at most m repetitions of the pattern
left toit.
Example to demonstrate using braces ({}) symbol:
import re
pattern1 = "m{1,2}"
pattern2 = "m{2}"
pattern3 = "m{3}"
string="This is Python programming Module-3"
result=re.findall(pattern1,string,re.I)
print("Printing m characters where minimum it contain 1 and maximum it contain 2
times:")
print(result)
result=re.findall(pattern2,string)
print("Printingmcharactersifastringcontainwordwithmrepeatedfor2times:") print(result)
result=re.findall(pattern3,string)
print("Printing an empty list:")
print(result)
Output:
Printing m characters where minimum it contain 1 and maximum it contain 2 times:
['mm', 'M']
Printing m characters if a string contain word with m repeated for 2 times:
['mm']
Printing an empty list:
[]
With this one symbol, we have just increased the flexibility of our regular expressions,
enabling the matching of more than just onestring.
Alternation is also sometimes called union or logicalOR.
Output:
The strings which matches with the given pattern are:
['RegEx', 'RegExr']
Output:
The string which matches with the given pattern is:
googoogle
Special Sequences:
Special sequences make commonly used patterns easier to write. Here's a list of special
sequences:
\A,\b,\B,\d,\D,\s,\S,\w,\W,\Z
Output 1:
Enter string: foot
Match
Output 2:
Enter string: afootball
No Match
Output 1:
Enter string: afoo
Match
Output 2:
Enter string: football
No Match
3. \B - Opposite of \b. Matches if the specified characters are not at the beginning or end of a
word.
Output 1:
Enter string: afootball
Match
Output 2:
Enter string: football
No Match
Output 1:
Enter string: foot
Match
Output 2:
Enter string: a foo
No Match
4. \d - Matches any decimal digit. Equivalent to[0-9]
Output 1:
Enter string: 123
Match
Output 2:
Enter string: Python
No Match
Output 1:
Enter string: Python
Match
Output 2:
Enter string: 123
No Match
6. \s - Matches where a string contains any whitespace character. Equivalent to [\t\n\r\f].
Output 1:
Enter string: Python Language
Match
Output 2:
Enter string: PythonLanguage
No Match
7. \S-Matcheswhereastringcontainsanynon-whitespacecharacter.Equivalentto[^\t\n\r\f].
Output 1:
Enter string: PythonLanguage
Match
Output 2:
Enterstring: (Empty Space)
NoMatch
8. \w - Matches any alphanumeric character (digits and alphabets). Equivalent to [a-zA-Z0-9_].
By the way, underscore _ is also considered analphanumeric character.
Output 1:
Enter string: Python_3
Match
Output 2:
Enter string: !$#@|)
No Match
Output 1:
Enter string: !$#@|)
Match
Output 2:
Enter string: Python_3
No Match
10. \Z-Matchesifthespecifiedcharactersareattheendofastring.
Output 1:
Enter string: I like Python
Match
Output 2:
Enter string: Python is fun
No Match
Output:
['MREC']
['MREC', 'JNTU']
RegEx Flags
Example:
import re
pattern=re.compile(r"(\+\d+)-(\d{10})")
result=pattern.search("The contact number is:+91-9012345678")
print(result)
Output:
<_sre.SRE_Match object; span=(22, 36), match='+91-9012345678'>
Using RegEx:
If we take regular expression as an inputthe syntax to perform search method is stated
below:
result = re.search(pattern, text)
The result will returns match object orNone
Note: Here patternis RegularExpression and Text can be string where we perform search
operation.
Example:
import re
result = re.search(r"(\+\d+)-(\d{10})","The contact number is:+91-9012345678")
print(result)
Output:
<_sre.SRE_Match object; span=(22, 36), match='+91-9012345678'>
2. match method:
re.match(): This function of re in Python will search the regular expression pattern and
return the firstoccurrence.
ThePythonRegExMatchmethodchecksfora matchonlyatthebeginningofthestring.
So,ifamatchisfoundinthefirst line,itreturnsthematchobject.
But if a match is found in some other line or it is not beginning of string then the Python
RegEx match function returnsNone.
Example:
import re
pattern=re.compile(r"(\+\d+)-(\d{10})")
result=pattern.match("The contact number is:+91-9012345678")
print(result)
Output:
None
Using RegEx :
If we take regular expression as an input the syntax to perform match method is stated
below:
result = re.match(pattern, text)
The result will returns match object orNone
Note: Here pattern isRegularExpression and Text can be string where we perform match
operation.
Example:
import re
result = re.match(r"(\+\d+)-(\d{10})","+91-9012345678 is contact number")
print(result)
Output:
<_sre.SRE_Match object; span=(0, 14), match='+91-9012345678'>
Match objects
Python match objects are what regular expression methods search and matchreturn.
The two most important methods of match objects are group andgroups.
group(*groupN):
*groupN refers to any number of arguments, includingnone.
Returns one or more subgroups of thematch.
If there is a single argument, the result is a single string; if there are multiple arguments,
the result is a tuple with one item perargument.
Without no arguments, *groupN defaults to a single zeroargument.
If a *groupN argument is zero, the corresponding return value is the entire matching
string; if it is in the inclusive range [1..99], it is the string matching the corresponding
parenthesizedgroup.
If a group number is negative or larger than the number of groups defined in the pattern,
an IndexError exception israised.
If a group is contained in a part of the pattern that did not match, the corresponding result
isNone.
If a group is contained in a part of the pattern that matched multiple times, the last match
isreturned.
groups(default_value=None)
Return a tuple containing all the subgroups of the match, from 1 up to however many
groups are in thepattern.
The default_value argument is used for groups that did not participate in the match; it
defaults toNone.
result=re.match(r"(\+\d+)-(\d{10})","+91-9012345678iscontactnumber")
print(result.group()) #Entire Match Output: +91-9012345678
print(result.group(0)) #Entire Match Output: +91-9012345678
print(result.group(1)) #Sub group 1 Output:+91
print(result.group(2)) #Sub group 2 Output: 9012345678
print(result.group(1,2)) #Multiple arguments give a tuple Output: ('+91', '9012345678')
print(result.groups()) #Multiple arguments give a tuple Output: ('+91', '9012345678')
Apart from the two most common methods in match objects there are still some other
commonly methods and attributes of match objectare:
start():The start() function returns the index of the start of the matched substring. So for the
previous example if we consider match object i.e., result then to obtain start() using below
syntax.
print(result.start()) #Output: 0
span(): The span() function returns a tuple containing start and end index of the matched part.
print(result.span()) #Output:(0,14)
re and string: The re attribute of a matched object returns a regular expression object.
Similarly, string attribute returns the passedstring.
print(result.re) #Output:re.compile('(\\+\\d+)-(\\d{10})')
print(result.string) #Output: +91-9012345678 is the contact number
Example: Write a Python program to display the mobile number from the given string
using different match object methods and attributes.
import re
pattern=re.compile(r"(\+\d+)-(\d{10})")
result=pattern.search("The contact number is +91-9012345678")
print("The country code of mobile number is: " +result.group(1))
print("The mobile number excluding country code is: " +result.group(2))
print("Complete mobile number is: " +result.group())
print("Displaying mobile number in groups: "+str(result.groups()))
print("The starting index of the matched substring in the given string is: "+str(result.start()))
print("The end index of the matched substring in the given string is: "+str(result.end()))
print("The range index of the matched substring in the given string is: "+str(result.span()))
print("The regular expression is: "+str(result.re))
print("The string(text)of this example is: "+str(result.string))
Output:
The country code of mobile number is: +91
The mobile number excluding country code is: 9012345678
Complete mobile number is: +91-9012345678
Displaying mobile number in groups: ('+91', '9012345678')
The starting index of the matched substring in the given string is: 22
The end index of the matched substring in the given string is: 36
The range index of the matched substring in the given string is: (22, 36)
The regular expression is: re.compile('(\\+\\d+)-(\\d{10})')
The string(text)of this example is: The contact number is +91-9012345678
Named Groups:
GroupsareusedinPythoninordertoreferenceregularexpressionmatches.
By default, groups, without names, are referenced according to numerical order starting
with 1 .
Let's say we have a regular expression that has 3 subexpressions.
Auserentersinhisbirthdate,accordingtotheday,month, andyear.
Let's say the user must first enter the month, then the day, and then theyear.
Using the group() function in Python, without named groups, the first match (the day)
would be referenced using the statement, group(1). The second match (the month) would
be referenced using the statement, group(2). The third match (the year) would be
referenced using the statement,group(3).
Now, with named groups, we can name each match in the regular expression. So instead
of referencing matches of the regular expression with numbers (group(1), group(2), etc.),
we can reference matches with names, such as group(‘day'), group(‘month'),
group('year').
Named groups makes the code more organized and morereadable.
By seeing, group(1), you don't really know what thisrepresents.
Butifyou see,group('month')orgroup('year'),youknowit'sreferencingthemonthorthe year.
So named groups makes code more readable and more understandable rather than the
default numericalreferencing.
Syntax:
(?P<group_name>regexp)
3. findallmethod:
re.findall(): findall() module is used to search for “all” occurrences that match a given pattern.
In contrast, search() module will only return the first occurrence that matches the
specifiedpattern.
findall() will iterate over all the lines of the file and will return all non-overlapping
matches of pattern in a singlestep.
Example:
import re
pattern=re.compile(r"(\+\d+\-\d{10})")
result=pattern.findall("The contact numbers are: +91-9012345678 and +91-
9876543210")
for results in result:
print(results)
Output:
+91-9012345678
+91-9876543210
Using RegEx:
If we take regular expression as an inputthe syntax to perform findall method is stated
below:
result = re.findall(pattern, text)
The result will returns match object or EmptyList
Note: Here pattern is Regular Expression and Text can be string where we perform search
operation.
Example:
import re
result=re.findall(r"(\+\d+\-\d{10})","The contact numbers are: +91-9012345678 and
+91-9876543210")
for results in result:
print(results)
Output:
+91-9012345678
+91-9876543210
4. splitmethod:
re.split(): This method will split a string based on a regular expression pattern in Python. The
Pythons re module’s re.split() method split the string by the occurrences of the regex pattern,
returning a list containing the resulting substrings.
Python RegEx split operations
Syntax:
re.split(pattern, string, maxsplit=0, flags=0)
The regular expression pattern and target string are the mandatoryarguments.
The maxsplit, and flags are optional.
pattern: the regular expression pattern used for splitting the targetstring.
string:Thevariablepointingtothetargetstring(i.e.,thestringwewanttosplit).
maxsplit: The number of splits you wanted toperform. If maxsplit is nonzero, at
mostmaxsplitsplitsoccur,andtheremainderofthestringisreturnedasthefinalelement of
thelist.
flags: By default, no flags areapplied.
Return value
Itsplitthetargetstringaspertheregularexpressionpattern,andthematchesarereturned in the
form of alist.
If the specified pattern is not found inside the target string, then the string is not split in
anyway,butthesplitmethodstillgeneratesalistsincethisisthewayit’sdesigned.
However, the list contains just one element, the target stringitself.
Output:
['Students', 'are', 'learning', 'Regular', 'Expression', 'and', 'this', 'topic', 'is', 'of', 'Module-3', 'of',
'Python', 'programming']
Output:
['Students', 'are learning Regular Expression\nand this topic is of Module-3 of Python
programming']
Output:
['01', '01', '2000']
5. sub /subnmethod:
re.sub(): The method returns a string where matched occurrences are replaced with the content
of replace variable. So it will substitute all occurrences unless max provided.
Syntax:
re.sub(pattern, replace, string, 0)
pattern: the regular expression pattern used for substituting the string with the value of
replacevariable
replace:thevaluewhichwillbereplacedinplaceofthe matchwhichoccursbypattern.
string: The string which acts as a source for replacement of values (i.e., the string we
want to perform substitution and to store theresult in another variable).
Max number: The number of maximum substitution you wanted to perform. If this
numberisnonzero,atmostthatnumberofsubstitutionoccurs.Bydefaultitwillbezero.
Example
import re
string = "MREC is a reputedcollege"
#pattern =r"\s"match="***" result1
= re.sub(r"\s","***",string)
print(result1)
#pattern =r"\s" match=""
result2 =re.sub(r"\s","",string,2)
print(result2)
Output:
MREC***is***a***reputed***college
MRECisa reputed college
re.subn():The re.subn() is similar to re.sub() except it returns a tuple of 2 items containing the
new string and the number of substitutions made.
Example
import re
string = "MREC is a reputedcollege"
#pattern =r"\s"match="***" result1
= re.subn(r"\s","***",string)
print(result1)
#pattern =r"\s"match="" result2
=re.subn(r"\s","",string,2)
print(result2)
Output:
('MREC***is***a***reputed***college', 4)
('MRECisa reputed college', 2)
PROGRAMS
1. DevelopaPythonprogramtoextractallemailaddressesfromthegivenstring.
Code:
importre
string= """This is Jack and anyone can communicate with this email id's,
which are [email protected] and [email protected]"""
result = re.findall("([a-zA-Z0-9_.]+@[a-zA-Z0-9]+\.[a-z.]+)", string)
for email in result:
print(email)
Output:
[email protected]@g
mail.com
Output 1:
Enter any string: Python3
The given string contains only the specified character(s)
Output 2:
Enter any string: !@#$
The given string contains none specified character(s)
3.Develop a Python program that matches a string that has an a followed by zero or more
b's.
Code:
import re
string=input("Enter string:")
pattern ='ab*?'
ifre.search(pattern,string):
print('Match')
else:
print('No match')
Output 1:
Enter string: abba
Match
Output 2:
Enter string: bbbc
No match
Output :
MREC:one:of the top reputed college in Hyderabad
5.Develop a Python program to match a string that contains only upper and lowercase
letters, numbers, andunderscores.
Code:
import re
string=input("Enter any string: ")
pattern='^[a-zA-Z0-9_]*$'
if re.search(pattern , string):
print("Pattern matches")
else:
print("No match")
Output 1:
Enter any string: MREC is a reputed college
No match
Output 2:
Enter any string:MREC_is_a_reputed_college
Patternmatches
Output:
Date in YYYY-MM-DD Format: 2021-04-15
Date in DD-MM-YYYY Format: 15-04-2021
MULTI THREADING
INTRODUCTION
Multi Tasking:
Executing several tasks simultaneously is the concept ofmultitasking.
There are 2 types of MultiTasking
1. Process based MultiTasking
2. Thread based MultiTasking
2. Thread basedMultitasking:
Executing several tasks simultaneously where each task is a seperate independent part of
the same program, is called Thread based multi tasking, and each independent part is
called aThread.
This type of multi tasking is best suitable at programmaticlevel.
Note: Whether it is process based or thread based, the main advantage of multi tasking is to
improve performance of the system by reducing response time.
Note: Where ever a group of independent jobs are available, then it is highly recommended to
execute simultaneously instead of executing one by one.
For such type of caseswe should go for MultiThreading.
Python provides one inbuilt module "threading" to provide support for developing
threads.
Hence developing multi threaded Programs is very easy inpython
THREADS
A thread has a beginning, an execution sequence, and aconclusion.
It has an instruction pointer that keeps track of where within its context it is currently
running.
It can be preempted (interrupted) and temporarily put on hold (also known as sleeping)
while other threads are running this is calledyielding.
Multiple threads within a process share the same data space with the main thread and can
therefore share information or communicate with one another more easily than if they
were separateprocesses.
Threads are generally executed in a concurrent fashion, and it is this parallelism and data
sharing that enable the coordination of multipletasks.
Naturally, it is impossible to run truly in a concurrent manner in a single CPU system, so
threads are scheduled in such a way that they run for a little bit, then yield to other
threads (going to the proverbial "back of the line" to await more CPU time again).
Throughout the execution of the entire process, each thread performs its own, separate
tasks, and communicates the results with other threads asnecessary.
PROCESSES
Computerprogramsaremerely executables,binary(orotherwise),whichresideondisk.
They do not take on a life of their own until loaded into memory and invoked by the
operatingsystem.
A process (sometimes called a heavyweight process) is a program in execution. Each
process has its own address space, memory, a data stack, and other auxiliary data to keep
track ofexecution.
The operating system manages the execution of all processes on the system, dividing the
time fairly between all processes. Processes can also fork or spawn new processes to
perform other tasks, but each new process has its own memory, data stack, etc., and
cannotgenerallyshareinformationunlessinterprocesscommunication(IPC)isemployed
Main Thread: Every Python Program by default contains one thread which is nothing but Main
Thread.
Creating Thread:
The ways of Creating Thread in Python:
We can create a thread in Python by using 3 ways
1. Creating a Thread without using anyclass
2. Creating a Thread by extending Threadclass
3. Creating a Thread without extending Threadclass
Ex:-
t = Thread(target=disp, args=(10,20))
If multiple threads present in our program, then we cannot expect execution order and
hence we cannot expect exact output for the multi threadedprograms.
B'z of this we cannot provide exact output for the aboveprogram.
Itisvariedfrommachinetomachineandruntorun.
Note: Thread is a pre defined class present in threading module which can be used to create our
own Threads.
Demo Program 1:
from threading import Thread
def disp(a, b):
print("Thread Running:", a, b)
t = Thread(target=disp, args=(10, 20))
t.start()
Output:
Thread Running: 10 20
Demo Program 2:
from threading import Thread
def disp(a, b):
print("Thread Running:", a, b)
for i in range(5):
t = Thread(target=disp, args=(10, 20))
t.start()
Output:
Thread Running: 1020
Thread Running: 1020
Thread Running: 1020
Thread Running: 1020
Thread Running: 1020
Ex:-
thread_object.name = ‘String’
print(thread_object.name)
Output:
MainThread
MREC
MREC
MREC Campus
Ex:-
class Mythread(Thread):
pass
t = Mythread()
Demo Program 2:
from threading import *
class MyThread(Thread):
def run(self):
for i in range(5):
print("Child Thread-1")
t=MyThread()
t.start()
t.join()
for i in range(5):
print("Main Thread-1")
Output:
ChildThread-1
ChildThread-1
ChildThread-1
ChildThread-1
ChildThread-1
Main Thread-1
Main Thread-1
Main Thread-1
Main Thread-1
MainThread-1
Output:
Child thread running: 10 20
Demo Program:-
from threading import Thread
class Mythread:
def disp (self, a, b):
print(a, b)
myt = Mythread()
t=Thread(target=myt.disp,args=(10,20))
t.start()
Output:
10 20
Syntax:- Thread_object.ident
Ex:- t.ident
Demo_Ident Thread:
from threading import *
def test():
print("Child Thread")
t=Thread(target=test)
t.start()
print("Main Thread Identification Number:",current_thread().ident)
print("Child Thread Identification Number:",t.ident)
Output:
Child Thread
Main Thread Identification Number:9484
Child Thread Identification Number: 6408
Race Condition:
Race condition is a situation that occurs when threads are acting in an unexpected
sequence, thus leading to unreliableoutput.
This can be eliminated using threadsynchronization.
Demo_Program_Race _condition:
else:
print("Sorry! All seats has alloted")
t = Train(1)
t1=Thread(target=t.reserve,args=(1,),name="John")
t2=Thread(target=t.reserve,args=(1,),name="Jack")
t1.start()
t2.start()
Output:
Available seat:Available seat:11
1 seat is alloted for John1 seat is alloted for Jack
Thread Synchronization:
Many threads trying to access the same object can lead to problems like making data
inconsistent or getting unexpectedoutput.
So when a thread is already accessing an object, preventing any other thread accessing
the same object is called ThreadSynchronization.
The object on which the threads are synchronized is called Synchronized Object or
Mutually Exclusive Lock(mutex).
Thread Synchronization is recommended when multiple threads are acting on the same
objectsimultaneously.
Locks:
Locks are typically used to synchronize access to a sharedresource.
Lock can be used to lock the object in which the thread isacting.
ALockhasonlytwostates,lockedandunlocked.Itiscreatedintheunlockedstate.
acquire( ):
Thismethodisusedtochangesthestatetolockedandreturnsimmediately.
When the state is locked, acquire() blocks until a call to release() in another thread
changesittounlocked,thentheacquire()callresetsittolockedandreturns.
Timeout-Wheninvokedwiththefloating-pointtimeoutargumentsettoapositivevalue, block
for at most the number of seconds specified by timeout and as long asthe lock cannot be
acquired. A timeout argument of -1 specifies an unbounded wait. It is forbidden to
specify a timeout when blocking isfalse.
The return value is True if the lock is acquired successfully, False if not (for example if
the timeoutexpired).
release( ):
This method is used to release a lock. This can be called from any thread, not only the
thread which has acquired thelock.
When the lock is locked, reset it to unlocked, and return. If any other threads areblocked
waiting for the lock to become unlocked, allow exactly one of them toproceed.
When invoked on an unlocked lock, a RuntimeError israised.
There is no returnvalue.
Syntax:-release( )
Lock_Demo Program:
from threading import *
class Train:
def __init__(self,available_seat):
self.available_seat = available_seat
self.l = Lock()
print(self.l)
else:
print("Sorry! All seats has alloted")
self.l.release()
t = Train(2)
t1 = Thread(target=t.reserve, args=(1,),name ="John")
t2 = Thread(target=t.reserve, args=(1,),name ="Jack")
t3=Thread(target=t.reserve,args=(1,),name="harry")
t1.start()
t2.start()
t3.start()
t1,t2,t3.join()
print("Main Thread")
Output:
<unlocked_thread.lockobjectat0x0000028AE063ED80>
Available seat:2
1 seat is alloted forJohn
Available seat:1
1 seat is alloted forJack
Available seat:0
Sorry! All seats has alloted
Main Thread
RLock:
Areentrantlockisa synchronizationprimitivethatmaybeacquiredmultipletimesbythe
samethread.
The standard Lock doesn’t know which thread is currently holding thelock.
If the lock is held, any thread that attempts to acquire it will block, even if the same
threaditselfisalreadyholdingthelock.Insuchcases,RLock(re-entrantlock)isused.
A reentrant lock must be released by the thread that acquired it. Once a thread has
acquired a reentrant lock, the same thread may acquire it again without blocking; the
thread must release it once for each time it has acquiredit.
RLock_Demo Program:
from threading import *
class Train:
def __init__(self,available_seat):
self.available_seat = available_seat
self.l = RLock()
print(self.l)
else:
print("Sorry! All seats has alloted")
self.l.release()
t = Train(2)
t1 = Thread(target=t.reserve, args=(1,),name ="John")
t2 = Thread(target=t.reserve, args=(1,),name ="Jack")
t3=Thread(target=t.reserve,args=(1,),name="Harry")
t1.start()
t2.start()
t3.start()
Output:
<unlocked _thread.RLock object owner=0 count=0 at 0x0000028AE0315B40>
<locked _thread.RLock object owner=1712 count=1 at 0x0000028AE0315B40>
Available seat: 2
1 seat is alloted for John
<locked _thread.RLock object owner=1644 count=1 at 0x0000028AE0315B40>
Available seat: 1
1 seat is alloted for Jack
<locked _thread.RLock object owner=1452 count=1 at 0x0000028AE0315B40>
Available seat: 0
Sorry! All seats has allotted
Semaphore:
In Lock and RLock, at a time only one Thread is allowed to execute but sometimes our
requirement is to execute a particular number of Threads at atime.
Suppose we have to allow at a time 10 members to access the Database and only 4
members are allowed to access NetworkConnection.
To handle such types of requirements we can not use Lock and RLock concept and here
we should go forSemaphore.
Semaphore can be used to limit the access to the shared resources with limitedcapacity.
It is an advanced part of synchronization.
This is one of the oldest synchronization primitives in the history of computer science,
invented by the early Dutch computer scientist Edsger W. Dijkstra,
Case 2 :
object_name.Semaphore(n)
In this case, a Semaphore object can be accessed by n Threads at atime.
The remaining Threads have to wait until releasing thesemaphore.
Semaphore_Demo_Program:
# importing the modules
from threading import *
import time
# creating instance
def display(name):
Output:
Hello, Hello, Hello, Thread-2Thread-3
Thread-1
Hello, Hello,
Hello, Thread-4Thread-5
Thread-6
Dead Lock:
A Deadlock is a situation where each of the process waits for a resource which is being
assigned to some anotherprocess.
In this situation, none of the process gets executed since the resource it needs, is held by
some other process which is also waiting for some other resource to bereleased.
Deadlocks are the most feared issue that developers face when writing
concurrent/multithreadedapplicationsinpython.Thebest waytounderstanddeadlocksis by
using the classic computer science example problem known as the Dining
PhilosophersProblem.
The problem statement for dining philosophers is asfollows:
Five philosophers are seated on a round table with five plates of spaghetti (a type of
pasta) and five forks, as shown in thediagram.
At any given time, a philosopher must either be eating orthinking.
Moreover, a philosopher must take the two forks adjacent to him (i.e., the left and right
forks) before he can eat the spaghetti. The problem of deadlock occurs when all five
philosophers pick up their right forkssimultaneously.
Since each of the philosophers has one fork, they will all wait for the others to put their
fork down. As a result, none of them will be able to eatspaghetti.
Similarly, in a concurrent system, a deadlock occurs when different threads or processes
(philosophers)trytoacquirethesharedsystemresources(forks)atthesametime.
As a result, none of the processes get a chance to execute as they are waiting for another
resource held by some otherprocess.
Dining Philosophers Problem
The ThreadModule
The thread module has long been deprecated. Starting with Python 3, it has been
designatedasobsoleteandisonlyaccessibleas__threadfor backwardcompatibility.
We can use the higher-level threading module for applications which you intend to
deploy. Howeverthethread module can be covered here for educational purposes.
Syntax:
The syntax to create a new thread using this module is as follows:
thread.start_new_thread(function_name, arguments)
Daemon Thread:
Adaemonthreadisathreadwhichrunscontinuouslyinthebackground.
It provides support to non-daemonthreads.
When last non-daemon thread terminates, automatically all daemon threads will be
terminated. We are not required to terminate daemon threadexplicitly.
The main objective of Daemon Threads is to provide support for Non Daemon Threads( likemain
thread)
Eg: Garbage Collector
daemon Property - This property is used to check whether a thread is daemon or not. It returns
True if thread is daemon else False.
We can also use daemon property to set a thread as daemon thread or vice versa.
isDaemon() - This method is used to check whether a thread is daemon or not. It returns True if
thread is daemon else False.
Eg:
from threading import *
print(current_thread().isDaemon()) #False
print(current_thread().daemon) #False
isAlive():
isAlive() method checks whether a thread is still executing or not.
Syntax
t1.isAlive()
True or False
active_count():
This function returns the number of active threads currently running.
Active_count_demo _program:
from threading import *
import time
def display():
print(current_thread().getName(),"...started")
time.sleep(3)
print(current_thread().getName(),"...ended")
print("TheNumberofactiveThreads:",active_count())
t1=Thread(target=display,name="ChildThread1")
t2=Thread(target=display,name="ChildThread2")
t3=Thread(target=display,name="ChildThread3")
t1.start()
t2.start()
t3.start()
print("The Number of active Threads:",active_count())
time.sleep(5)
print("The Number of active Threads:",active_count())
Output:
The Number of active Threads: 1
ChildThread1 ...started
ChildThread2 ...started
ChildThread3 ...started
The Number of active Threads: 4
ChildThread1 ...ended
ChildThread2 ...ended
ChildThread3 ...ended
The Number of active Threads: 1
enumerate() function:
This function returns a list of all active threads currently running.
Enumerate_function_demo_program:
from threading import *
import time
def display():
print(current_thread().getName(),"...started")
time.sleep(3)
print(current_thread().getName(),"...ended")
t1=Thread(target=display,name="ChildThread1")
t2=Thread(target=display,name="ChildThread2")
t3=Thread(target=display,name="ChildThread3")
t1.start()
t2.start()
t3.start()
l=enumerate()
for t inl:
print("Thread Name:",t.name)
time.sleep(5)
l=enumerate()
for t in l:
print("Thread Name:",t.name)
Output:
ChildThread1 ...started
ChildThread2 ...started
ChildThread3 ...started
Thread Name: MainThread
Thread Name: ChildThread1
Thread Name: ChildThread2
Thread Name: ChildThread3
ChildThread1 ...ended
ChildThread2 ...ended
ChildThread3 ...ended
Thread Name: MainThread
Thread Communication:
Two or more threads communicate with each other.
Event
Condition
Queue
Event:
This is one of the simplest mechanisms for communication between threads: one thread
signals an event and other threads wait forit.
An event object manages an internal flag that can be set to true with the set() method and
reset to false with the clear()method.
The wait() method blocks until the flag istrue.
The flag is initiallyfalse.
Event Methods:
set()- It sets the internal flag to true. All threads waiting for it to become true are awakened.
Threads that call wait() once the flag is true will not block at all.
clear()- It resets the internal flag to false. Subsequently, threads calling wait() will block until
wait(timeout=None) –
It blocks until the internal flag is true. If the internal flag is true on entry, return
immediately. Otherwise, block until another thread calls set() to set the flag to true, or
until the optional timeoutoccurs.
When the timeout argument is present and not None, it should be a floating pointnumber
specifying a timeout for the operation in seconds (or fractionsthereof).
This method returns true if and only if the internal flag has been set to true, either before
the wait call or after the wait starts, so it will always return True except if a timeout is
given and the operation timesout.
Event_Demo_Program:
from threading import Thread,Event
from time import sleep
def traffic_lights():
sleep(2)
e.set()
print("Green Light Enabled")
sleep(4)
print("Red Light Enabled")
e.clear()
def traffic():
e.wait()
while e.is_set():
print("You can Drive...")
sleep(0.5)
print("Program Completed")
e=Event()
t1 =Thread(target=traffic_lights)
t2 = Thread(target=traffic)
t1.start()
t2.start()
Output:
Green Light EnabledYou can Drive...
Condition:
Condition class is used to improve speed of communication between Threads. The
condition class object is called conditionvariable.
Aconditionvariableisalwaysassociatedwith somekindoflock;thiscanbepassedinor one will
be created bydefault.
Passing one in is useful when several condition variables must share the same lock. The
lock is part of the condition object: you don’t have to track itseparately.
A condition is a more advanced version of the eventobject.
notify(n=1) – This method is used to immediately wake up one thread waiting on the
condition. Where n is number of thread need to wakeup.
notify_all()–Thismethodisusedtowakeupallthreadswaitingonthecondition.
wait(timeout=None) – This method wait until notified or until a timeout occurs. If the
callingthreadhasnotacquiredthelockwhenthismethodiscalled,aRuntimeErroris
raised. Wait terminates when invokes notify() method or notify_all() method. The return value is
True unless a given timeout expired, in which case it is False.
Condition_Demo_Program:
from threading import Thread,Condition
from time importsleep
List = []
def produce():
co.acquire()
for i in range(1,5):
List.append(i)
sleep(1)
print("ItemProduced...")
co.notify()
co.release()
def consume():
co.acquire()
co.wait(timeout=0)
co.release()
print(List)
co = Condition()
t1 = Thread(target=produce)
t2 = Thread(target=consume)
t1.start()
t2.start()
Output:
ItemProduced...
ItemProduced...
ItemProduced...
ItemProduced...
[1, 2, 3,4]
Queue:
TheQueueclass ofqueue moduleisusefultocreateaqueuethatholdsthe dataproduced by
theproducer.
The data can be taken from the queue and utilized by theconsumer.
We need not use locks since queues are threadsafe.
Queue Methods:
put ( )– This method is used by Producer to insert items into the queue.
Syntax:- queue_object.put(item)
Ex:- q.put(i)
get ( )– This method is used by Consumer to retrieve items from the queue.
Syntax:- producer_object.queue_object.get(item)
Ex:- p.q.get(i)
empty() – This method returns True if queue is Empty else returns False.
Ex:- q.empty()
full() – This method returns True if queue is Full else returns False.
Ex:- q.full()
Producer-Consumer Demo_Program:
from threading import Thread
from queue import Queue
from time import sleep
class Producer:
def __init__(self):
self.q =Queue()
defproduce(self):
for i in range(1,5):
print("Item Produced",i)
self.q.put(i)
sleep(1)
class Consumer:
def __init__(self,prod):
self.prod = prod
def consumer(self):
for i in range(1,5):
print("Item Recieved",self.prod.q.get(i))
p = Producer()
c = Consumer(p)
t1 =
Thread(target=p.produce) t2
= Thread(target=c.consumer)
t1.start()
t2.start()
Output:
Item Produced1
Item Recieved1
Item Produced2
Item Recieved2
Item Produced3
Item Recieved3
Item Produced4
Item Recieved4
RELATED MODULES
The below lists some of the modules you may use when programming multithreaded
applications
Module Description
thread Obsoleteinpython3.xandwhichisbasic,lower-levelthreadmodule
threading Higher-level threading and synchronizationobjects
queue Synchronized FIFO queue for multiple threads
socketserver TCPandUDPmanagerswithsomethreadingcontrol