Multitasking in Python
When you use your phone or computer, you see that you can run several programs together at the same time, each program running in memory is consideredProcessFor example, if you run five programs together, this means that the operating system organizes the work of fiveProcessesWith some. The mechanism of running several programs together is calledMultiprocessing.
If you use your computer applications, you should use five drivers with some processes. The mechanism for running several processing programs.
On the other hand, in the same program, you can execute several commands together and make the user feel that they are being executed simultaneously. For example, if you are playing a game such as football, you find that there are several things that happen at the same time. For example, when you play the game, you hear several Sounds (such as an enthusiastic song, the commentator's voice, the fans' voice, the referee's whistle sound in the event of a mistake, etc..), in addition to the fact that you can move the player and watch the timing of the match and many other details that all happen at the same time to make you a great game. This mechanism is calledMultithreading,Because each running part of the program is a set of commands placed insideThreadSpecial.
On the other hand, in one program, you can execute several commands together and make the user feel as if they are being executed simultaneously, for example if you are playing a game such as a soccer game, you find that there are several things happening At the same time, for example when you start the game you hear several sounds (such as a passionate song, the voice of the commentator, the voice of the fans, the sound of the referee's whistle in case of a mistake, etc.) , in addition to that you can move the player and watch the timing of the match and many other details that all happen at the same time to make you a great game. This mechanism is called multithreading, because each running part of the program is a set of commands placed inside a special thread.
So we use a mechanismMultithreadingTo make the program able to execute several commands together as if they are executing simultaneously, and this is what we will learn in this lesson about multitasking in Python .
If we use the Multithreading mechanism to make the program able to execute several commands together, as if they are executed simultaneously, and this is what we will learn in this lesson.
The importance of multitasking
The importance of multitasking is as follows:
Make the user able to perform several operations with each other at the same time.
Make the application design more beautiful and add effects to it.
AllThreadYou run it, it works in isolation from the rest of the commands in the program, and therefore, in the event of any error in thetheThreadIt will not affect the rest of the commands in the program, nor does it affect anyThreadThe last one in the program.
The importance of multitasking Makes the user able to perform several operations simultaneously. Make the design of applications more beautiful and add effects to it. Each Thread that you run works separately from the rest of the commands in the program, and therefore, in the event of any error in the Thread, it will not affect the rest of the commands in the program, as it does not affect any other thread running in the program.
Create methodThreadin python
Initially, starting with version 2.4 in Python, the module became the module threadingused to createThreads.
This module is a ready-made module in Python, and it contains the class Threadthat is used to buildThreadand control it.
How to create a Thread in Python? Initially, starting with version 2.4 in Python, threading became the module used to create Threads. This module is a ready-made module in Python. It contains a Thread class which is used to build a Thread and control it.
Whatch out
Before this module, there was a module named _threadfor this purpose as well, but it is no longer used now and will be canceled in the future.
Therefore, we advise not to use the module _threador rely on it.
building stepsThread in Python
Module must be included
threading.Building a class inherits from the class
Threadand you doOverridefor a function whose name isrun(),And in it you put the commands that you want to be executed when it is launchedtheThread.
Operation stepsThread in Python
An object must be created from the class that inherits from the class
Thread.From this object, we call a ready-made function whose name
start()will automatically call the functionrun()and execute the commands placed in it.
In the following example, we created a class named Workerinherit from the classThread.
In the function __init__()for this class, we have defined a property with its name namebecause we intend to give a name to every object we create from this class.
We also made it call the function __init__()in the class Threadto be able to treat any object we create from this classKThread.
Then we didOverrideThe function run()is intended to print the name we put in the property namethree times when it is run.
Finally, we create two objects of this class and run them simultaneously.
In the following example, we create a class named Worker that inherits from the Thread class. In the __init __ () function for this class, we have defined an attribute named name because we intend to give a name to every object we create from this class. We also made it happen to call the function __init __ () in the Thread class to be able to treat any object we create from this class as a Thread. Then we did Override to the run() function in order to print the name that we put in the name property three times when it is run. Finally, we created two objects from this class and ran them simultaneously.
Example
Example
import threading # Thread We have included this module so that we can inherit from the class
import time # which we will use in the example sleep() We include this module because it contains the
# Thread function that inherits from the Worker class Here we have created a class called
class Worker(threading.Thread):
# Thread in the __init__() class In order to call the __init__() function here we have
also defined the # name function, in order to specify that a name must be passed to the object that is created from the class and which will be stored in the property
def __init__(self, name):
super(Worker, self).__init__()
self.name = name
# To determine what will happen when we run the object we create from this class run() here we define the function
def run(self):
# Initially the name of the object will be printed and it has started
print('Starting', self.name)
# sleep() After that the object name will be printed 3 times. And we called the function
# and passed the number 1 to it to make the loop stop for a second at the end of each cycle
for i in range(3):
print(self.name)
time.sleep(1)
# At the end the object name will be printed and it is finished Execute it
print('Ending', self.name )
# Worker we created in the Worker module Here we included the class
from Worker import Worker
# Threads ie we created two. Worker here we created two class objects
thread1 = Worker('Thread-1')
thread2 = Worker('Thread-2')
# once from each run() object of both objects to run. That is, the start() function will be called. Here we called the
thread1.start() function thread2.start
()
# to make the python interpreter thread2 and thread1 from the two join() objects. Here we called the function
# before it continued executing the rest of the commands in the file thread2 and thread1 waits for the two objects
thread1.join()
and thread2.join() to stop
completely, the next print command thread2 and thread1 will be executed after the two objects have stopped
print('Both threads are end')
• We will get a result similar to the following when we run the fileTest.
Thread-1
Starting Thread-2
Thread-2
Thread-2
Thread-1
Thread-2
Thread-1
Ending Thread-2
Ending Thread-1
Both threads are end
note
In the previous example, you could delete line 12 because the class Workeralso inherited a property named nameafter it from the classThread.
Therefore, you can pass the name directly to the property that the class inherited Workerinstead of defining it in it again.
Technical information
When running more thanThreadSimultaneously, you cannot guarantee or limit anyThreadIt will run out or expire before the other.
The reason for this is that the computer processor(CPU)will send allThreadYou run it into a kernel(Core)So he executes them for you at once.
And logically, a kernel that has less stress will end up executing commandstheThreadFaster.
For this reason, if you run the previous example more than once, you will find that each time you will get a different result from the run.
Technical information When running more than one Thread at a time, you cannot guarantee or specify which Thread will run out or end before the other. The reason for this is that the computer processor (CPU) will send every thread you run to the core so that it can execute them for you simultaneously. Logically, a kernel with less pressure will finish executing Thread commands faster. For this reason, if you run the previous example more than once, you will find that each time you will get a different result from running.
ConcepttheMain Threadin python
In Python, every code that is executed in a program, it must be executed insideThreadat least one.
That is, even if you don't put the code insideThreadIt will be put inThread.
And therefore if you runThreadIn the program, it means that the program is currently running in twoThreadsand notThreadOne.
In the following example, we have printed a numbertheThreadsThose who are currently executing, knowing that we have not created any object from a class that inherits from the classThread.
In the following example, we printed the number of Threads that are currently executing, noting that we did not create any class object that inherits from the thread. Example
Example
import threading # Thread We have included this module so that we can inherit from the class
# which are currently running Threads Here we have printed the number of the
print('Active thread(s) count:', threading.active_count())
# turned on by the main thread in the program. i.e. the first Thread here we have printed the name of the
print('Main thread object:', threading.main_thread().name)
# the current being executed Thread here we have printed the name of the
print('Current thread object:', threading.main_thread() .name)
• We will get a result similar to the following when we run the fileTest.
Main thread object: MainThread
Current thread object: MainThread
• We note that the numbertheThreadsWho are currently executing is1 ,This proves that the basic code in the program is placed inThread.
• As the name oftheThreadprimary and nountheThreadWhich is currently runningMainThread.
Module functions threadingin Python
The following table contains the threadingmost frequently used module functions that we have already used in the previous examples.
| Function name and definition | |
|---|---|
threading.active_count()
returns the numbertheThreadswho are executing at the time it was called. |
|
threading.main_thread()
return an objectthethreadcore in the programme. Information: the threadBasic in the program is the firstThreadThe Python interpreter started executing the commands placed in it. |
|
threading.current_thread()
return an objectthethreadWhich is executed at the time it was called. |
|
threading.enumerate()
Returns an object listcontaining every object threadexecuting at the time it was called. Note: Do not return any that threadare turned off or not turned on in the first place. |
|
Class functions and properties Threadin Python
The following table contains the Threadmost commonly used class functions that we have already used in the previous examples.
| Function name and definition | |
|---|---|
run()
do herOverrideLet's put in it the commands we want to be executed when an object is runThe Thread. |
|
start()
used to operate an objecttheThreadwho summoned her. Actually, the function start()only calls the function run()to carry out the commands placed in it. Note: it is not possible to play the same objectthe ThreadMore than once. That is, the function cannot be called start()more than once from the same objectThe Thread.If the function is called start()twice from the same objecttheThreadIt throws the exceptionRuntimeError . |
|
is_alive()
Returns Trueas long as an objecttheThreadIts implementation is not finished yet even if it was not started in the first place. Otherwise, you will return False. |
|
join(timeout=None)
make an objecttheThreadThe one who called it is waiting for the execution to finishtheThreadThe one who works before him before he starts executing the commands in it. In case you want to delay the executionthe ThreadWhich will run when execution is finishedtheThreadFor a specified time, you can pass the parameter place number timeoutrepresenting this period, noting that the number you pass represents the waiting time in seconds. For example, if you pass the number 1.5 , it means that you mean a second and a half. Technical Information This function is important when you need to maketheThreadsThey run out one after the other instead of all at once and cause a problemDeadlock. And don't worry if you don't know what the term meansDeadlockNow because you will understand it later from the examples. In the event that the Python interpreter finds that when it will runthe Threadwill happenDeadlock,You will throw the exceptionRuntimeError . |
|
The following table contains the characteristics of the classThread.
| The name of the property and its definition | |
|---|---|
name
Returns the name given to an objecttheThreadwho summoned her. Actually, when creating an object from the class that inherits from the class Threadyou can pass the name you want to give it the moment it is created. |
|
ident
Return the tariff number(ID)Which is randomly generated and given to an objecttheThreadwho summoned her. |
|
daemon
This feature can be used if you intend to turn onThreadfrom insideThreadelse. If you pass it the value Truebefore you runtheThreadOther, the Python interpreter will understand that you intend to turn offtheThreadthe other automatically when it stopstheThreadwho called him in the first place. Also, if it wastheThreadThe other is connected to a file, to a database, to the Internet, etc.. Closing it suddenly does not guarantee that the connections it was making will be closed. In the event that the Python interpreter finds that when it will runthe Threadwill happenDeadlock,You will throw the exceptionRuntimeError . |
|
Sync in Python
In case you want to run more thanThreadAt the same time, you should pay close attention to the operations that eachThreadYou intend to run it because this command may cause you logical problems or give you wrong results as we will show you in the following scenarios.
Sync in Python In case you want to run more than one Thread at the same time, you must pay close attention to the operations that will be performed by each Thread that you intend to run, because this command may cause you to logic problems or give you wrong results as we will show you in the following scenarios.Scenario one
If you buildThreadHis task is to fetch the student’s grades stored in a database and then calculate his general average, and after the average was calculated and the average was presented to the student, heThreadAnother modified some marks in the database because he found that the student had a lot of absence.
So, the result it gave ustheThreadThe first in this case is not correct, as it was assumed that the average was calculated after the days of absence were entered into the equation that calculated his final average and exposed him if he was successful based on his final average and the number of days he attended the university.
For example, it may be one of the university's conditions that if a student is absent for 30 days during one semester, he will be considered to have failed in all subjects.
So, to solve the previous problem, it was necessary to synchronize the worktheThreadI andtheThreadSecond.
ie had to runtheThreadWhich brings the days of absence first.
Then after storing the days of absence and stoppingtheThreadFor work, you must runtheThreadWhich brings the student's marks and gives him the final result.
second scenario
If there isThreadHe wants to modify the content of a file, and it is thereThreadAnother reads the content of the same file.
In this case, an error will also occur, which is thattheThreadThe one who is reading, will read the content of the old file, without knowing that the content of this file was updated at the time he was reading from it and performing operations based on the content he read at the time.
To solve this problem, it was necessary to synchronize the worktheThreadwho reads from the file andtheThreadWhich modifies the file to ensure that they do not deal with it simultaneously.
Third Scenario
If you run twoThreads,And at some point the two got stuck becausetheThreadThe first need to have access to something to usetheThreadSecond. and at the same timetheThreadThe second needs to have access to something to usetheThreadthe first. This dilemma is calledDeadlock,And you can leave it as shown in the following picture.
To solve this problem, it was possible to run allThreadalone.
Third scenario If you run two Threads, then at some point the two get stuck because the first Thread needs to access something that the second Thread uses. At the same time, the second Thread needs to access something that the first Thread will use. This dilemma is called Deadlock, and you can clear it up as in the following picture. Sync in Python To work around this problem, it was possible to run each Thread separately.In the following example we modified the previous example to maketheThreadsThose we raise from the classes Workerwork synchronously, that is, one after the other and not with each other.
What we did was simply create an object out of classLock,Then put the code we want to be executed synchronously inside a block of this object.
Note: We have marked the lines we added in the previous code in yellow.
In the following example, we have modified the previous example to make the Threads we create from the worker class work simultaneously, that is, one after the other and not together. What we just did is create an object from the class Lock, then put the code that we want it to be executed simultaneously in a block of that object. Note: We mark the lines we added on the previous code with yellow. Example
Example
import threading # Thread We have included this module so that we can inherit from the class
import time # which we will use in the example sleep() We have included this module because it contains the function
# because we will use it to make any object we create from the class run synchronously Lock Here we have created an object from the class
lock = threading.Lock()
# Thread inherits from the Worker class Here we have created a class named
class Worker(threading.Thread):
# Thread in the __init__() class in order to call the function __init__() here we have defined the function
# name also, from In order to specify that a name must be passed to the object being created from the class, which will be stored in the property
def __init__(self, name):
super(Worker, self).__init__()
self.name = name
# To determine what will happen when we run the object we create from this class run() here we define the function
def run(self):
# Here we make the code run synchronously
with lock:
# Initially the name of the object will be printed and its execution has started
print( 'Starting', self.name)
# sleep() Then the object name will be printed 3 times. And we called the function
# and passed the number 1 to it to make the loop stop for a second at the end of each cycle
for i in range(3):
print(self.name)
time.sleep(1)
# At the end the object name will be printed and it is finished Execute it
print('Ending', self.name )
# Worker we created in the Worker module Here we included the class
from Worker import Worker
# Threads ie we created two. Worker here we created two class objects
thread1 = Worker('Thread-1')
thread2 = Worker('Thread-2')
# once from each run() object of both objects to run. That is, the start() function will be called. Here we called the
thread1.start() function thread2.start
()
# to make the python interpreter thread2 and thread1 from the two join() objects. Here we called the function
# before it continued executing the rest of the commands in the file thread2 and thread1 waits for the two objects
thread1.join()
and thread2.join() to stop
completely, the next print command thread2 and thread1 will be executed after the two objects have stopped
print('Both threads are end')
• We will get the following result when we run the fileTest.
Thread-1
Thread-1
Thread-1
Ending Thread-1 <-- the first Thread here has finished executing the orders
Starting Thread-2 <-- the second Thread here The execution has begun The
Thread-2
Thread-2
Thread-2
Ending Thread-2 <-- the second Thread Here the execution of the commands
Both threads are end
If you want to apply the sync method without using the . methodwith block:,The code you want to sync must be placed between the functions acquire()andrelease().
So you can write the function code run()as follows and get the same result.
def run(self):
block.acquire() # Here we make the code to be executed synchronously
print('Starting', self.name)
for i in range(3):
print(self.name)
time.sleep (1)
print('Ending', self.name)
block.release() # Here we stop the synchronization
to gathertheThreadsInside Queuein Python
In case you want to run a groupThreadsSimultaneously, you can create an object from classes Queueand place them in it.
Then you create a loop to go throughThreadOne of them at a time, and then you turn it on.
The following table contains the Queuemost commonly used class functions.
| Function name and definition | |
|---|---|
get()
Returns the next element of an objecttheQueueWho summoned it and then you delete it. In our case, you will returnThreadNew every time we call it up. If it was an object the QueueWhen called, it throws the exceptionEmpty . |
|
put(item)
It adds the object we pass to it as an element in an objecttheQueuewho summoned her. In our case, we pass an object of class that representsThread. |
|
qsize()
Returns the number of elements in an objecttheQueuewho summoned her. In our case a numbertheThreadsexisting and those that have not yet been implemented. |
|
empty()
Used to find out if an object istheQueueWho called it empty or not. Returns Trueif empty, otherwise returnsFalse. |
|
Full()
Used to find out if an object istheQueueWho called it full or not, ie able to store new items or not. Returns Trueif the number of objects placed in it is less than the number of objects it can store, otherwise returnsFalse. |
|
In the following example, we have created three objects representingThreadsAnd we temporarily put them inlistits namelistWorkers.
Then we store objectsthelistWorkersinQueueits namequeueWorkers.
Finally we ran alltheThreadsThe two subjects in the objectqueueWorkers.
Note: we madetheThreadsThey work synchronously.
So if you don't want to make them run simultaneously, you'll just have to remove the sentencewith lock:placed in the functionrun().
Example
import threading # Thread We have included this module so that we can inherit from the class
import time # which we will use in the example sleep() We have included this module because it contains the function
# because we will use it to make any object we create from the class run synchronously Lock Here we have created an object from the class
lock = threading.Lock()
# Thread inherits from the Worker class Here we have created a class named
class Worker(threading.Thread):
# Thread in the __init__() class in order to call the function __init__() here we have defined the function
# name also, from In order to specify that a name must be passed to the object being created from the class, which will be stored in the property
def __init__(self, name):
super(Worker, self).__init__()
self.name = name
# To determine what will happen when we run the object we create from this class run() here we define the function
def run(self):
# Here we make the code run synchronously
with lock:
# Initially the name of the object will be printed and its execution has started
print( 'Starting', self.name)
# sleep() Then the object name will be printed 3 times. And we called the function
# and passed the number 1 to it to make the loop stop for a second at the end of each cycle
for i in range(3):
print(self.name)
time.sleep(1)
# At the end the object name will be printed and it is finished Execute it
print('Ending', self.name )
from Worker import Worker # Worker that we created in the Worker module here we included the
from queue import Queue # queue class in the Queue module here we included
the # Thread class ie we put 3 objects representing Worker in it we put 3 objects from the class list Here we created
workerList = [
Worker('Thread-1'),
Worker('Thread-2'),
Worker('Thread-3')
]
# Because we want to put the same elements inside a workerList whose number of elements is equal to the number of elements of the Queue object here we created a
workerQueue object = Queue(len(workerList))
# workerQueue and then you add it as an element in the workerList object every cycle returns an object from the for objects here we created a loop
# workerQueue in the workerList object At the end all objects in the object
for thread in workerList:
workerQueue.put(thread)
# non-empty workerQueue does not stop iterating inside as long as the while object here we created loop
# and then execute workerQueue from Worker object In each cycle of the loop, it will output a
while not workerQueue.empty():
workerQueue.get().start()
object Every cycle returns one of the objects in the for here we created a
# loop to make the interpreter null Python does not execute any other commands that exist after the join() loop returns it. It will call the Worker function each object
for thread in workerList:
thread.join()
# Exactly, the next print command thread3 and thread2 , thread1 will be executed after the objects have stopped
print('All threads are end')
• We will get the following result when we run the fileTest.
Thread-1
Thread-1
Thread-1
Ending Thread-1 <-- the first Thread here has finished executing the orders
Starting Thread-2 <-- the second Thread here The execution has begun The
Thread-2
Thread-2
Thread-2
Ending Thread-2 <-- the second Thread here has finished executing the orders
Starting Thread-3 <-- the third Thread here The
Thread-3
Thread-3
Thread-3
Ending Thread- has been started 3 <-- The third Thread here is finished
All threads are end
the difference betweentheProcessAnd thetheThreadgenerally
ProcessIt means a program that is currently running, and the operating system has reserved a special space for it in memory.
ThreadIt is a set of commands that are executed while executing other commands in the same program. You can run more thanThreadAt the same time in the program, information can also be shared between them. Noting that all are createdtheThreadsWithin the reserved spaceforProcessin the memory.